This commit is contained in:
Esophose 2018-11-11 22:56:51 -07:00
commit 06b9fb812f
95 changed files with 8622 additions and 5142 deletions

3
.gitignore vendored
View file

@ -37,7 +37,8 @@ Icon
/bin
/.settings
/doc
/target
/target
/images
# Files that might appear on external disk
.Spotlight-V100

360
LICENSE Normal file
View file

@ -0,0 +1,360 @@
Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International
Public License
By exercising the Licensed Rights (defined below), You accept and agree
to be bound by the terms and conditions of this Creative Commons
Attribution-NonCommercial-ShareAlike 4.0 International Public License
("Public License"). To the extent this Public License may be
interpreted as a contract, You are granted the Licensed Rights in
consideration of Your acceptance of these terms and conditions, and the
Licensor grants You such rights in consideration of benefits the
Licensor receives from making the Licensed Material available under
these terms and conditions.
Section 1 -- Definitions.
a. Adapted Material means material subject to Copyright and Similar
Rights that is derived from or based upon the Licensed Material
and in which the Licensed Material is translated, altered,
arranged, transformed, or otherwise modified in a manner requiring
permission under the Copyright and Similar Rights held by the
Licensor. For purposes of this Public License, where the Licensed
Material is a musical work, performance, or sound recording,
Adapted Material is always produced where the Licensed Material is
synched in timed relation with a moving image.
b. Adapter's License means the license You apply to Your Copyright
and Similar Rights in Your contributions to Adapted Material in
accordance with the terms and conditions of this Public License.
c. BY-NC-SA Compatible License means a license listed at
creativecommons.org/compatiblelicenses, approved by Creative
Commons as essentially the equivalent of this Public License.
d. Copyright and Similar Rights means copyright and/or similar rights
closely related to copyright including, without limitation,
performance, broadcast, sound recording, and Sui Generis Database
Rights, without regard to how the rights are labeled or
categorized. For purposes of this Public License, the rights
specified in Section 2(b)(1)-(2) are not Copyright and Similar
Rights.
e. Effective Technological Measures means those measures that, in the
absence of proper authority, may not be circumvented under laws
fulfilling obligations under Article 11 of the WIPO Copyright
Treaty adopted on December 20, 1996, and/or similar international
agreements.
f. Exceptions and Limitations means fair use, fair dealing, and/or
any other exception or limitation to Copyright and Similar Rights
that applies to Your use of the Licensed Material.
g. License Elements means the license attributes listed in the name
of a Creative Commons Public License. The License Elements of this
Public License are Attribution, NonCommercial, and ShareAlike.
h. Licensed Material means the artistic or literary work, database,
or other material to which the Licensor applied this Public
License.
i. Licensed Rights means the rights granted to You subject to the
terms and conditions of this Public License, which are limited to
all Copyright and Similar Rights that apply to Your use of the
Licensed Material and that the Licensor has authority to license.
j. Licensor means the individual(s) or entity(ies) granting rights
under this Public License.
k. NonCommercial means not primarily intended for or directed towards
commercial advantage or monetary compensation. For purposes of
this Public License, the exchange of the Licensed Material for
other material subject to Copyright and Similar Rights by digital
file-sharing or similar means is NonCommercial provided there is
no payment of monetary compensation in connection with the
exchange.
l. Share means to provide material to the public by any means or
process that requires permission under the Licensed Rights, such
as reproduction, public display, public performance, distribution,
dissemination, communication, or importation, and to make material
available to the public including in ways that members of the
public may access the material from a place and at a time
individually chosen by them.
m. Sui Generis Database Rights means rights other than copyright
resulting from Directive 96/9/EC of the European Parliament and of
the Council of 11 March 1996 on the legal protection of databases,
as amended and/or succeeded, as well as other essentially
equivalent rights anywhere in the world.
n. You means the individual or entity exercising the Licensed Rights
under this Public License. Your has a corresponding meaning.
Section 2 -- Scope.
a. License grant.
1. Subject to the terms and conditions of this Public License,
the Licensor hereby grants You a worldwide, royalty-free,
non-sublicensable, non-exclusive, irrevocable license to
exercise the Licensed Rights in the Licensed Material to:
a. reproduce and Share the Licensed Material, in whole or
in part, for NonCommercial purposes only; and
b. produce, reproduce, and Share Adapted Material for
NonCommercial purposes only.
2. Exceptions and Limitations. For the avoidance of doubt, where
Exceptions and Limitations apply to Your use, this Public
License does not apply, and You do not need to comply with
its terms and conditions.
3. Term. The term of this Public License is specified in Section
6(a).
4. Media and formats; technical modifications allowed. The
Licensor authorizes You to exercise the Licensed Rights in
all media and formats whether now known or hereafter created,
and to make technical modifications necessary to do so. The
Licensor waives and/or agrees not to assert any right or
authority to forbid You from making technical modifications
necessary to exercise the Licensed Rights, including
technical modifications necessary to circumvent Effective
Technological Measures. For purposes of this Public License,
simply making modifications authorized by this Section 2(a)
(4) never produces Adapted Material.
5. Downstream recipients.
a. Offer from the Licensor -- Licensed Material. Every
recipient of the Licensed Material automatically
receives an offer from the Licensor to exercise the
Licensed Rights under the terms and conditions of this
Public License.
b. Additional offer from the Licensor -- Adapted Material.
Every recipient of Adapted Material from You
automatically receives an offer from the Licensor to
exercise the Licensed Rights in the Adapted Material
under the conditions of the Adapter's License You apply.
c. No downstream restrictions. You may not offer or impose
any additional or different terms or conditions on, or
apply any Effective Technological Measures to, the
Licensed Material if doing so restricts exercise of the
Licensed Rights by any recipient of the Licensed
Material.
6. No endorsement. Nothing in this Public License constitutes or
may be construed as permission to assert or imply that You
are, or that Your use of the Licensed Material is, connected
with, or sponsored, endorsed, or granted official status by,
the Licensor or others designated to receive attribution as
provided in Section 3(a)(1)(A)(i).
b. Other rights.
1. Moral rights, such as the right of integrity, are not
licensed under this Public License, nor are publicity,
privacy, and/or other similar personality rights; however, to
the extent possible, the Licensor waives and/or agrees not to
assert any such rights held by the Licensor to the limited
extent necessary to allow You to exercise the Licensed
Rights, but not otherwise.
2. Patent and trademark rights are not licensed under this
Public License.
3. To the extent possible, the Licensor waives any right to
collect royalties from You for the exercise of the Licensed
Rights, whether directly or through a collecting society
under any voluntary or waivable statutory or compulsory
licensing scheme. In all other cases the Licensor expressly
reserves any right to collect such royalties, including when
the Licensed Material is used other than for NonCommercial
purposes.
Section 3 -- License Conditions.
Your exercise of the Licensed Rights is expressly made subject to the
following conditions.
a. Attribution.
1. If You Share the Licensed Material (including in modified
form), You must:
a. retain the following if it is supplied by the Licensor
with the Licensed Material:
i. identification of the creator(s) of the Licensed
Material and any others designated to receive
attribution, in any reasonable manner requested by
the Licensor (including by pseudonym if
designated);
ii. a copyright notice;
iii. a notice that refers to this Public License;
iv. a notice that refers to the disclaimer of
warranties;
v. a URI or hyperlink to the Licensed Material to the
extent reasonably practicable;
b. indicate if You modified the Licensed Material and
retain an indication of any previous modifications; and
c. indicate the Licensed Material is licensed under this
Public License, and include the text of, or the URI or
hyperlink to, this Public License.
2. You may satisfy the conditions in Section 3(a)(1) in any
reasonable manner based on the medium, means, and context in
which You Share the Licensed Material. For example, it may be
reasonable to satisfy the conditions by providing a URI or
hyperlink to a resource that includes the required
information.
3. If requested by the Licensor, You must remove any of the
information required by Section 3(a)(1)(A) to the extent
reasonably practicable.
b. ShareAlike.
In addition to the conditions in Section 3(a), if You Share
Adapted Material You produce, the following conditions also apply.
1. The Adapter's License You apply must be a Creative Commons
license with the same License Elements, this version or
later, or a BY-NC-SA Compatible License.
2. You must include the text of, or the URI or hyperlink to, the
Adapter's License You apply. You may satisfy this condition
in any reasonable manner based on the medium, means, and
context in which You Share Adapted Material.
3. You may not offer or impose any additional or different terms
or conditions on, or apply any Effective Technological
Measures to, Adapted Material that restrict exercise of the
rights granted under the Adapter's License You apply.
Section 4 -- Sui Generis Database Rights.
Where the Licensed Rights include Sui Generis Database Rights that
apply to Your use of the Licensed Material:
a. for the avoidance of doubt, Section 2(a)(1) grants You the right
to extract, reuse, reproduce, and Share all or a substantial
portion of the contents of the database for NonCommercial purposes
only;
b. if You include all or a substantial portion of the database
contents in a database in which You have Sui Generis Database
Rights, then the database in which You have Sui Generis Database
Rights (but not its individual contents) is Adapted Material,
including for purposes of Section 3(b); and
c. You must comply with the conditions in Section 3(a) if You Share
all or a substantial portion of the contents of the database.
For the avoidance of doubt, this Section 4 supplements and does not
replace Your obligations under this Public License where the Licensed
Rights include other Copyright and Similar Rights.
Section 5 -- Disclaimer of Warranties and Limitation of Liability.
a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE
EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS
AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF
ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS,
IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION,
WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS,
ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT
KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT
ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU.
b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE
TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION,
NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT,
INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES,
COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR
USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN
ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR
DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR
IN PART, THIS LIMITATION MAY NOT APPLY TO YOU.
c. The disclaimer of warranties and limitation of liability provided
above shall be interpreted in a manner that, to the extent
possible, most closely approximates an absolute disclaimer and
waiver of all liability.
Section 6 -- Term and Termination.
a. This Public License applies for the term of the Copyright and
Similar Rights licensed here. However, if You fail to comply with
this Public License, then Your rights under this Public License
terminate automatically.
b. Where Your right to use the Licensed Material has terminated under
Section 6(a), it reinstates:
1. automatically as of the date the violation is cured, provided
it is cured within 30 days of Your discovery of the
violation; or
2. upon express reinstatement by the Licensor.
For the avoidance of doubt, this Section 6(b) does not affect any
right the Licensor may have to seek remedies for Your violations
of this Public License.
c. For the avoidance of doubt, the Licensor may also offer the
Licensed Material under separate terms or conditions or stop
distributing the Licensed Material at any time; however, doing so
will not terminate this Public License.
d. Sections 1, 5, 6, 7, and 8 survive termination of this Public
License.
Section 7 -- Other Terms and Conditions.
a. The Licensor shall not be bound by any additional or different
terms or conditions communicated by You unless expressly agreed.
b. Any arrangements, understandings, or agreements regarding the
Licensed Material not stated herein are separate from and
independent of the terms and conditions of this Public License.
Section 8 -- Interpretation.
a. For the avoidance of doubt, this Public License does not, and
shall not be interpreted to, reduce, limit, restrict, or impose
conditions on any use of the Licensed Material that could lawfully
be made without permission under this Public License.
b. To the extent possible, if any provision of this Public License is
deemed unenforceable, it shall be automatically reformed to the
minimum extent necessary to make it enforceable. If the provision
cannot be reformed, it shall be severed from this Public License
without affecting the enforceability of the remaining terms and
conditions.
c. No term or condition of this Public License will be waived and no
failure to comply consented to unless expressly agreed to by the
Licensor.
d. Nothing in this Public License constitutes or may be interpreted
as a limitation upon, or waiver of, any privileges and immunities
that apply to the Licensor or You, including from the legal
processes of any jurisdiction or authority.

21
pom.xml
View file

@ -2,7 +2,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.esophose.playerparticles</groupId>
<artifactId>PlayerParticles</artifactId>
<version>5.2</version>
<version>5.3</version>
<name>PlayerParticles</name>
<url>https://github.com/Esophose/PlayerParticles</url>
<description>Display particles around your player using customized styles and data!</description>
@ -54,7 +54,7 @@
</excludes>
</filter>
</filters>
<outputFile>C:\Users\Esophose\Desktop\Spigot Dev Servers\1.13\plugins\update\PlayerParticles v5.2.jar</outputFile>
<outputFile>C:\Users\Esophose\Desktop\Spigot Dev Servers\1.13\plugins\update\PlayerParticles v5.3.jar</outputFile>
</configuration>
</execution>
<execution>
@ -81,7 +81,7 @@
</excludes>
</filter>
</filters>
<outputFile>C:\Users\Esophose\Desktop\Spigot Dev Servers\1.12\plugins\update\PlayerParticles v5.2.jar</outputFile>
<outputFile>C:\Users\Esophose\Desktop\Spigot Dev Servers\1.12\plugins\update\PlayerParticles v5.3.jar</outputFile>
</configuration>
</execution>
<execution>
@ -108,7 +108,7 @@
</excludes>
</filter>
</filters>
<outputFile>C:\Users\Esophose\Desktop\Spigot Dev Servers\1.11\plugins\update\PlayerParticles v5.2.jar</outputFile>
<outputFile>C:\Users\Esophose\Desktop\Spigot Dev Servers\1.11\plugins\update\PlayerParticles v5.3.jar</outputFile>
</configuration>
</execution>
<execution>
@ -135,7 +135,7 @@
</excludes>
</filter>
</filters>
<outputFile>C:\Users\Esophose\Desktop\Spigot Dev Servers\1.10\plugins\update\PlayerParticles v5.2.jar</outputFile>
<outputFile>C:\Users\Esophose\Desktop\Spigot Dev Servers\1.10\plugins\update\PlayerParticles v5.3.jar</outputFile>
</configuration>
</execution>
<execution>
@ -162,7 +162,7 @@
</excludes>
</filter>
</filters>
<outputFile>C:\Users\Esophose\Desktop\Spigot Dev Servers\1.9\plugins\update\PlayerParticles v5.2.jar</outputFile>
<outputFile>C:\Users\Esophose\Desktop\Spigot Dev Servers\1.9\plugins\update\PlayerParticles v5.3.jar</outputFile>
</configuration>
</execution>
</executions>
@ -191,10 +191,15 @@
<artifactId>HikariCP</artifactId>
<version>3.2.0</version>
</dependency>
<dependency>
<groupId>org.xerial</groupId>
<artifactId>sqlite-jdbc</artifactId>
<version>3.23.1</version>
</dependency>
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId>
<version>1.13.1-R0.1-SNAPSHOT</version>
<version>1.13.2-R0.1-SNAPSHOT</version>
</dependency>
</dependencies>
</project>
</project>

View file

@ -1,291 +0,0 @@
/**
* 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;
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.manager.ParticleManager;
import com.esophose.playerparticles.particles.ParticleEffect;
import com.esophose.playerparticles.particles.ParticleEffect.BlockData;
import com.esophose.playerparticles.particles.ParticleEffect.ItemData;
import com.esophose.playerparticles.particles.ParticleEffect.NoteColor;
import com.esophose.playerparticles.particles.ParticleEffect.OrdinaryColor;
import com.esophose.playerparticles.particles.ParticleEffect.ParticleColor;
import com.esophose.playerparticles.particles.ParticleEffect.ParticleData;
import com.esophose.playerparticles.particles.ParticleEffect.ParticleProperty;
import com.esophose.playerparticles.styles.DefaultStyles;
import com.esophose.playerparticles.styles.api.ParticleStyle;
import com.esophose.playerparticles.util.ParticleUtils;
public class PPlayer {
/**
* The UUID of the player
*/
private final UUID playerUUID;
/**
* The effect and style the player is using
*/
private ParticleEffect particleEffect;
private ParticleStyle particleStyle;
/**
* All data used to display custom particles
*/
private ItemData particleItemData;
private BlockData particleBlockData;
private OrdinaryColor particleColorData;
private NoteColor particleNoteColorData;
/**
* Constructs a new PPlayer
*
* @param uuid The player UUID
* @param effect The player's effect
* @param style The player's style
* @param itemData The player's item data
* @param blockData The player's block data
* @param colorData The player's color data
* @param noteColorData The player's note color data
*/
public PPlayer(UUID uuid, ParticleEffect effect, ParticleStyle style, ItemData itemData, BlockData blockData, OrdinaryColor colorData, NoteColor noteColorData) {
this.playerUUID = uuid;
this.setParticleEffect(effect);
this.setParticleStyle(style);
this.setItemData(itemData);
this.setBlockData(blockData);
this.setColorData(colorData);
this.setNoteColorData(noteColorData);
}
/**
* Gets the player's UUID
*
* @return The player's UUID
*/
public UUID getUniqueId() {
return this.playerUUID;
}
/**
* Gets the Player from their UUID
*
* @return The player if they are online, null if they are offline
*/
public Player getPlayer() {
return Bukkit.getPlayer(this.playerUUID);
}
/**
* Gets the player's particle effect
*
* @return The player's particle effect
*/
public ParticleEffect getParticleEffect() {
return this.particleEffect;
}
/**
* Gets the player's particle style
*
* @return The player's particle style
*/
public ParticleStyle getParticleStyle() {
if (this.particleStyle == null) return DefaultStyles.NONE;
return this.particleStyle;
}
/**
* Gets the player's item data
*
* @return The player's item data
*/
public ItemData getItemData() {
return this.particleItemData;
}
/**
* Gets the player's block data
*
* @return The player's block data
*/
public BlockData getBlockData() {
return this.particleBlockData;
}
/**
* Gets the player's color data
*
* @return The player's color data
*/
public OrdinaryColor getColorData() {
return this.particleColorData;
}
/**
* Gets the player's note color data
*
* @return The player's note color data
*/
public NoteColor getNoteColorData() {
return this.particleNoteColorData;
}
/**
* Sets the player's particle effect
*
* @param effect The player's new particle effect
*/
public void setParticleEffect(ParticleEffect effect) {
if (effect == null) effect = ParticleEffect.NONE;
this.particleEffect = effect;
}
/**
* Sets the player's particle style
*
* @param style The player's new particle style
*/
public void setParticleStyle(ParticleStyle style) {
if (style == null) style = DefaultStyles.NONE;
this.particleStyle = style;
}
/**
* Sets the player's item data
*
* @param itemData The player's new item data
*/
public void setItemData(ItemData itemData) {
if (itemData == null) itemData = new ItemData(ParticleUtils.closestMatchWithFallback("IRON_SHOVEL", "IRON_SPADE"));
this.particleItemData = itemData;
}
/**
* Sets the player's block data
*
* @param blockData The player's new block data
*/
public void setBlockData(BlockData blockData) {
if (blockData == null) blockData = new BlockData(Material.STONE);
this.particleBlockData = blockData;
}
/**
* Sets the player's color data
*
* @param colorData The player's new color data
*/
public void setColorData(OrdinaryColor colorData) {
if (colorData == null) colorData = new OrdinaryColor(0, 0, 0);
this.particleColorData = colorData;
}
/**
* Sets the player's note color data
*
* @param noteColorData The player's new note color data
*/
public void setNoteColorData(NoteColor noteColorData) {
if (noteColorData == null) noteColorData = new NoteColor(0);
this.particleNoteColorData = noteColorData;
}
/**
* 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_MATERIAL_DATA)) {
if (this.particleEffect == ParticleEffect.ITEM) {
return this.particleItemData;
} else {
return this.particleBlockData;
}
}
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 current particle data as a string
*
* @return The particle data in a human-readable string
*/
public String getParticleDataString() {
if (this.particleEffect == ParticleEffect.BLOCK || this.particleEffect == ParticleEffect.FALLING_DUST) {
return particleBlockData.getMaterial().toString().toLowerCase();
} else if (this.particleEffect == ParticleEffect.ITEM) {
return particleItemData.getMaterial().toString().toLowerCase();
} 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
*
* @param playerUUID The player's UUID
* @return A default PPlayer
*/
public static PPlayer getNewPPlayer(UUID playerUUID) {
ParticleEffect particleEffect = ParticleEffect.NONE;
ParticleStyle particleStyle = DefaultStyles.NONE;
ItemData particleItemData = new ItemData(ParticleUtils.closestMatchWithFallback("IRON_SHOVEL", "IRON_SPADE"));
BlockData particleBlockData = new BlockData(Material.STONE);
OrdinaryColor particleColorData = new OrdinaryColor(0, 0, 0);
NoteColor particleNoteColorData = new NoteColor(0);
return new PPlayer(playerUUID, particleEffect, particleStyle, particleItemData, particleBlockData, particleColorData, particleNoteColorData);
}
}

View file

@ -1,102 +0,0 @@
/**
* 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;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.bukkit.ChatColor;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.command.TabCompleter;
import org.bukkit.entity.Player;
import org.bukkit.util.StringUtil;
import com.esophose.playerparticles.manager.MessageManager.MessageType;
import com.esophose.playerparticles.manager.PPlayerDataManager;
import com.esophose.playerparticles.manager.PermissionManager;
import com.esophose.playerparticles.particles.ParticleEffect;
import com.esophose.playerparticles.particles.ParticleEffect.ParticleProperty;
import com.esophose.playerparticles.util.ParticleUtils;
public class ParticleCommandCompleter implements TabCompleter {
private static final String[] COMMANDS = { "help", "gui", "effect", "effects", "style", "styles", "data", "fixed", "reset", "worlds", "version" };
private static final String[] FIXED_COMMANDS = { "create", "remove", "list", "info" };
private static final List<String> BLOCK_MATERIALS = ParticleUtils.getAllBlockMaterials();
private static final List<String> ITEM_MATERIALS = ParticleUtils.getAllItemMaterials();
/**
* Activated when a user pushes tab in chat prefixed with /pp
*
* @param sender The sender that hit tab, should always be a player
* @param cmd The command the player is executing
* @param alias The possible alias for the command
* @param args All arguments following the command
* @return A list of commands available to the sender
*/
public List<String> onTabComplete(CommandSender sender, Command cmd, String alias, String[] args) {
if (!(sender instanceof Player)) return new ArrayList<String>();
List<String> completions = new ArrayList<String>();
if (cmd.getName().equalsIgnoreCase("pp")) {
if (args.length > 1) {
if (args[0].equalsIgnoreCase("effect") && args.length == 2) {
List<String> commands = PermissionManager.getEffectsUserHasPermissionFor((Player) sender);
StringUtil.copyPartialMatches(args[1], commands, completions);
} else if (args[0].equalsIgnoreCase("style") && args.length == 2) {
List<String> commands = PermissionManager.getStylesUserHasPermissionFor((Player) sender);
StringUtil.copyPartialMatches(args[1], commands, completions);
} else if (args[0].equalsIgnoreCase("fixed") && args.length > 1) {
if (args.length == 2) {
List<String> commands = Arrays.asList(FIXED_COMMANDS);
StringUtil.copyPartialMatches(args[1], commands, completions);
} else if (args[1].equalsIgnoreCase("create")) {
completions.add("<x> <y> <z> <effect> <style> [data]");
} else if ((args[1].equalsIgnoreCase("remove") || args[1].equalsIgnoreCase("info")) && args.length == 3) {
completions.add("<id>");
}
} else if (args[0].equalsIgnoreCase("data")) {
PPlayer pplayer = PPlayerDataManager.getInstance().getPPlayer(((Player) sender).getUniqueId());
if (pplayer == null) {
completions.add(ChatColor.stripColor(MessageType.NO_DATA_USAGE.getMessage()));
} else if (pplayer.getParticleEffect().hasProperty(ParticleProperty.REQUIRES_MATERIAL_DATA) && args.length == 2) {
if (pplayer.getParticleEffect() == ParticleEffect.ITEM) {
StringUtil.copyPartialMatches(args[1], ITEM_MATERIALS, completions);
} else {
StringUtil.copyPartialMatches(args[1], BLOCK_MATERIALS, completions);
}
} else if (pplayer.getParticleEffect().hasProperty(ParticleProperty.COLORABLE)) {
if (pplayer.getParticleEffect() == ParticleEffect.NOTE && args.length == 2) {
completions.add("<0-23>");
StringUtil.copyPartialMatches(args[args.length - 1], Arrays.asList(new String[] { "rainbow" }), completions);
} else if (pplayer.getParticleEffect() != ParticleEffect.NOTE && args.length > 1 && args.length < 5) {
completions.add("<0-255>");
if (args.length == 2) {
StringUtil.copyPartialMatches(args[args.length - 1], Arrays.asList(new String[] { "rainbow" }), completions);
}
}
} else if (args.length == 2) {
completions.add(ChatColor.stripColor(MessageType.NO_DATA_USAGE.getMessage()));
}
}
} else {
List<String> commands = new ArrayList<String>(Arrays.asList(COMMANDS));
StringUtil.copyPartialMatches(args[0], commands, completions);
}
}
return completions;
}
public static String[] getCommandsList() {
return COMMANDS;
}
}

View file

@ -1,815 +0,0 @@
/**
* 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;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.command.Command;
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.manager.PPlayerDataManager;
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.particles.FixedParticleEffect;
import com.esophose.playerparticles.particles.ParticleEffect;
import com.esophose.playerparticles.particles.ParticleEffect.BlockData;
import com.esophose.playerparticles.particles.ParticleEffect.ItemData;
import com.esophose.playerparticles.particles.ParticleEffect.NoteColor;
import com.esophose.playerparticles.particles.ParticleEffect.OrdinaryColor;
import com.esophose.playerparticles.particles.ParticleEffect.ParticleProperty;
import com.esophose.playerparticles.styles.DefaultStyles;
import com.esophose.playerparticles.styles.api.ParticleStyle;
import com.esophose.playerparticles.styles.api.ParticleStyleManager;
import com.esophose.playerparticles.util.ParticleUtils;
public class ParticleCommandExecutor implements CommandExecutor {
/**
* A list of all valid commands
*/
private static List<String> validCommands;
static {
validCommands = new ArrayList<String>();
validCommands.addAll(Arrays.asList(ParticleCommandCompleter.getCommandsList()));
}
/**
* Called when a player executes a /pp command
* Checks what /pp command it is and calls the correct method
*
* @param sender Who executed the command
* @param cmd The command
* @param label The command label
* @param args The arguments following the command
* @return True if everything went as planned (should always be true)
*/
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
if (!(sender instanceof Player)) return true;
Player p = (Player) sender;
if (args.length == 0) {
onGUI(p, true);
return true;
}
if (!validCommands.contains(args[0].toLowerCase())) {
MessageManager.sendMessage(p, MessageType.INVALID_ARGUMENTS);
return true;
}
String[] cmdArgs = new String[0];
if (args.length >= 2) cmdArgs = Arrays.copyOfRange(args, 1, args.length);
// Commands that don't require access to any effects
switch (args[0].toLowerCase()) {
case "help":
onHelp(p);
return true;
case "worlds":
onWorlds(p);
return true;
case "version":
onVersion(p);
return true;
case "effects":
onEffects(p);
return true;
case "styles":
onStyles(p);
return true;
case "style":
onStyle(p, cmdArgs);
return true;
}
// Commands that require access to effects
if (PermissionManager.getEffectsUserHasPermissionFor(p).size() != 1) {
final String[] f_cmdArgs = cmdArgs;
PPlayerDataManager.getInstance().getPPlayer(p.getUniqueId(), (pplayer) -> { // The PPlayer MUST be loaded before we can execute any of these commands
// If the player no longer has permission for their effect, remove it
if (!PermissionManager.hasEffectPermission(p, pplayer.getParticleEffect())) {
PPlayerDataManager.getInstance().savePPlayer(pplayer.getUniqueId(), ParticleEffect.NONE);
}
// If the player no longer has permission for their style, default to none
if (!PermissionManager.hasStylePermission(p, pplayer.getParticleStyle())) {
PPlayerDataManager.getInstance().savePPlayer(pplayer.getUniqueId(), DefaultStyles.NONE);
}
switch (args[0].toLowerCase()) {
case "effect":
onEffect(p, f_cmdArgs);
break;
case "data":
onData(p, f_cmdArgs);
break;
case "fixed":
onFixed(p, f_cmdArgs);
break;
case "reset":
onReset(p, f_cmdArgs);
break;
case "gui":
onGUI(p, false);
break;
}
});
} else {
MessageManager.sendMessage(p, MessageType.NO_PARTICLES);
}
return true;
}
/**
* Gets an online player by their username if they exist
*
* @param playerName The player's username to lookup
* @return The player, if they exist
*/
private Player getOnlinePlayerByName(String playerName) {
for (Player p : Bukkit.getOnlinePlayers())
if (p.getName().toLowerCase().contains(playerName.toLowerCase())) return p;
return null;
}
/**
* Called when a player uses /pp help
*
* @param p The player who used the command
*/
private void onHelp(Player p) {
MessageManager.sendMessage(p, MessageType.AVAILABLE_COMMANDS);
MessageManager.sendMessage(p, MessageType.COMMAND_USAGE);
}
/**
* Called when a player uses /pp worlds
*
* @param p The player who used the command
*/
private void onWorlds(Player p) {
if (PPlayerDataManager.getInstance().getDisabledWorlds() == null || PPlayerDataManager.getInstance().getDisabledWorlds().isEmpty()) {
MessageManager.sendMessage(p, MessageType.DISABLED_WORLDS_NONE);
return;
}
String worlds = "";
for (String s : PPlayerDataManager.getInstance().getDisabledWorlds()) {
worlds += s + ", ";
}
if (worlds.length() > 2) worlds = worlds.substring(0, worlds.length() - 2);
MessageManager.sendCustomMessage(p, MessageType.DISABLED_WORLDS.getMessage() + " " + worlds);
}
/**
* Called when a player uses /pp version
*
* @param p The player who used the command
*/
private void onVersion(Player p) {
MessageManager.sendCustomMessage(p, ChatColor.GOLD + "Running PlayerParticles v" + PlayerParticles.getPlugin().getDescription().getVersion());
MessageManager.sendCustomMessage(p, ChatColor.GOLD + "Plugin created by: Esophose");
}
/**
* Called when a player uses /pp data
*
* @param p The player who used the command
* @param args The arguments for the command
*/
private void onData(Player p, String[] args) {
ParticleEffect effect = PPlayerDataManager.getInstance().getPPlayer(p.getUniqueId()).getParticleEffect();
if ((!effect.hasProperty(ParticleProperty.REQUIRES_MATERIAL_DATA) && !effect.hasProperty(ParticleProperty.COLORABLE)) || args.length == 0) {
if (effect.hasProperty(ParticleProperty.COLORABLE)) {
if (effect == ParticleEffect.NOTE) {
MessageManager.sendMessage(p, MessageType.DATA_USAGE, "note");
MessageManager.sendCustomMessage(p, MessageType.USAGE.getMessage() + " " + MessageType.NOTE_DATA_USAGE.getMessage());
} else {
MessageManager.sendMessage(p, MessageType.DATA_USAGE, "color");
MessageManager.sendCustomMessage(p, MessageType.USAGE.getMessage() + " " + MessageType.COLOR_DATA_USAGE.getMessage());
}
} else if (effect.hasProperty(ParticleProperty.REQUIRES_MATERIAL_DATA)) {
if (effect == ParticleEffect.ITEM) {
MessageManager.sendMessage(p, MessageType.DATA_USAGE, "item");
MessageManager.sendCustomMessage(p, MessageType.USAGE.getMessage() + " " + MessageType.ITEM_DATA_USAGE.getMessage());
} else {
MessageManager.sendMessage(p, MessageType.DATA_USAGE, "block");
MessageManager.sendCustomMessage(p, MessageType.USAGE.getMessage() + " " + MessageType.BLOCK_DATA_USAGE.getMessage());
}
} else {
MessageManager.sendMessage(p, MessageType.NO_DATA_USAGE);
}
return;
}
if (effect.hasProperty(ParticleProperty.COLORABLE)) {
if (effect == ParticleEffect.NOTE) {
if (args[0].equalsIgnoreCase("rainbow")) {
PPlayerDataManager.getInstance().savePPlayer(p.getUniqueId(), new NoteColor(99));
MessageManager.sendMessage(p, MessageType.DATA_APPLIED, "note");
return;
}
int note = -1;
try {
note = Integer.parseInt(args[0]);
} catch (Exception e) {
MessageManager.sendMessage(p, MessageType.DATA_INVALID_ARGUMENTS, "note");
MessageManager.sendCustomMessage(p, MessageType.USAGE.getMessage() + " " + MessageType.NOTE_DATA_USAGE.getMessage());
return;
}
if (note < 0 || note > 23) {
MessageManager.sendMessage(p, MessageType.DATA_INVALID_ARGUMENTS, "note");
MessageManager.sendCustomMessage(p, MessageType.USAGE.getMessage() + " " + MessageType.NOTE_DATA_USAGE.getMessage());
return;
}
PPlayerDataManager.getInstance().savePPlayer(p.getUniqueId(), new NoteColor(note));
MessageManager.sendMessage(p, MessageType.DATA_APPLIED, "note");
} else {
if (args[0].equalsIgnoreCase("rainbow")) {
PPlayerDataManager.getInstance().savePPlayer(p.getUniqueId(), new OrdinaryColor(999, 999, 999));
MessageManager.sendMessage(p, MessageType.DATA_APPLIED, "color");
} else if (args.length >= 3) {
int r = -1;
int g = -1;
int b = -1;
try {
r = Integer.parseInt(args[0]);
g = Integer.parseInt(args[1]);
b = Integer.parseInt(args[2]);
} catch (Exception e) {
MessageManager.sendMessage(p, MessageType.DATA_INVALID_ARGUMENTS, "color");
MessageManager.sendCustomMessage(p, MessageType.USAGE.getMessage() + " " + MessageType.COLOR_DATA_USAGE.getMessage());
return;
}
if (r < 0 || r > 255 || g < 0 || g > 255 || b < 0 || b > 255) {
MessageManager.sendMessage(p, MessageType.DATA_INVALID_ARGUMENTS, "color");
MessageManager.sendCustomMessage(p, MessageType.USAGE.getMessage() + " " + MessageType.COLOR_DATA_USAGE.getMessage());
return;
}
PPlayerDataManager.getInstance().savePPlayer(p.getUniqueId(), new OrdinaryColor(r, g, b));
MessageManager.sendMessage(p, MessageType.DATA_APPLIED, "color");
} else {
MessageManager.sendMessage(p, MessageType.DATA_INVALID_ARGUMENTS, "color");
MessageManager.sendCustomMessage(p, MessageType.USAGE.getMessage() + " " + MessageType.COLOR_DATA_USAGE.getMessage());
}
}
} else if (effect.hasProperty(ParticleProperty.REQUIRES_MATERIAL_DATA)) {
if (effect == ParticleEffect.ITEM) {
Material material = null;
try {
material = ParticleUtils.closestMatch(args[0]);
if (material == null) material = Material.matchMaterial(args[0]);
if (material == null) throw new Exception();
} catch (Exception e) {
MessageManager.sendMessage(p, MessageType.DATA_MATERIAL_UNKNOWN, "item");
MessageManager.sendCustomMessage(p, MessageType.USAGE.getMessage() + " " + MessageType.ITEM_DATA_USAGE.getMessage());
return;
}
if (material.isBlock()) {
MessageManager.sendMessage(p, MessageType.DATA_MATERIAL_MISMATCH, "item");
MessageManager.sendCustomMessage(p, MessageType.USAGE.getMessage() + " " + MessageType.ITEM_DATA_USAGE.getMessage());
return;
}
PPlayerDataManager.getInstance().savePPlayer(p.getUniqueId(), new ItemData(material));
MessageManager.sendMessage(p, MessageType.DATA_APPLIED, "item");
} else {
Material material = null;
try {
material = ParticleUtils.closestMatch(args[0]);
if (material == null) material = Material.matchMaterial(args[0]);
if (material == null) throw new Exception();
} catch (Exception e) {
MessageManager.sendMessage(p, MessageType.DATA_MATERIAL_UNKNOWN, "block");
MessageManager.sendCustomMessage(p, MessageType.USAGE.getMessage() + " " + MessageType.BLOCK_DATA_USAGE.getMessage());
return;
}
if (!material.isBlock()) {
MessageManager.sendMessage(p, MessageType.DATA_MATERIAL_MISMATCH, "block");
MessageManager.sendCustomMessage(p, MessageType.USAGE.getMessage() + " " + MessageType.BLOCK_DATA_USAGE.getMessage());
return;
}
PPlayerDataManager.getInstance().savePPlayer(p.getUniqueId(), new BlockData(material));
MessageManager.sendMessage(p, MessageType.DATA_APPLIED, "block");
}
}
}
/**
* 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 args Additional arguments
*/
private void onReset(Player p, String[] args) {
if (args.length >= 1) {
String altPlayerName = args[0];
if (!PermissionManager.canUseForceReset(p)) {
MessageManager.sendMessage(p, MessageType.FAILED_EXECUTE_NO_PERMISSION, altPlayerName);
} else {
Player altPlayer = getOnlinePlayerByName(altPlayerName);
if (altPlayer == null) {
MessageManager.sendMessage(p, MessageType.FAILED_EXECUTE_NOT_FOUND, altPlayerName);
} else {
PPlayerDataManager.getInstance().resetPPlayer(altPlayer.getUniqueId());
MessageManager.sendMessage(altPlayer, MessageType.RESET);
MessageManager.sendMessage(p, MessageType.EXECUTED_FOR_PLAYER, altPlayer.getName());
}
}
} else {
PPlayerDataManager.getInstance().resetPPlayer(p.getUniqueId());
MessageManager.sendMessage(p, MessageType.RESET);
}
}
/**
* Called when a player uses /pp effect
*
* @param p The player who used the command
* @param args The arguments for the command
*/
private void onEffect(Player p, String[] args) {
if (args.length == 0) {
MessageManager.sendMessage(p, MessageType.INVALID_TYPE);
return;
}
String argument = args[0];
if (ParticleManager.effectFromString(argument) != null) {
ParticleEffect effect = ParticleManager.effectFromString(argument);
if (!PermissionManager.hasEffectPermission(p, effect)) {
MessageManager.sendMessage(p, MessageType.NO_PERMISSION, effect.getName());
return;
}
PPlayerDataManager.getInstance().savePPlayer(p.getUniqueId(), effect);
if (effect != ParticleEffect.NONE) {
MessageManager.sendMessage(p, MessageType.NOW_USING, effect.getName());
} else {
MessageManager.sendMessage(p, MessageType.CLEARED_PARTICLES);
}
return;
}
MessageManager.sendMessage(p, MessageType.INVALID_TYPE);
}
/**
* Called when a player uses /pp effects
*
* @param p The player who used the command
*/
private void onEffects(Player p) {
if (PermissionManager.getEffectsUserHasPermissionFor(p).size() == 1) {
MessageManager.sendMessage(p, MessageType.NO_PARTICLES);
return;
}
String toSend = MessageType.USE.getMessage() + " ";
for (ParticleEffect effect : ParticleEffect.getSupportedEffects()) {
if (PermissionManager.hasEffectPermission(p, effect)) {
toSend += effect.getName() + ", ";
continue;
}
}
if (toSend.endsWith(", ")) {
toSend = toSend.substring(0, toSend.length() - 2);
}
MessageManager.sendCustomMessage(p, toSend);
MessageManager.sendCustomMessage(p, MessageType.USAGE.getMessage() + " " + MessageType.PARTICLE_USAGE.getMessage());
}
/**
* Called when a player uses /pp style
*
* @param p The player who used the command
* @param args The arguments for the command
*/
private void onStyle(Player p, String[] args) {
if (PermissionManager.getStylesUserHasPermissionFor(p).size() == 1) {
MessageManager.sendMessage(p, MessageType.NO_STYLES);
return;
}
if (args.length == 0) {
MessageManager.sendMessage(p, MessageType.INVALID_TYPE_STYLE);
return;
}
String argument = args[0];
if (ParticleStyleManager.styleFromString(argument) != null) {
ParticleStyle style = ParticleStyleManager.styleFromString(argument);
if (!PermissionManager.hasStylePermission(p, style)) {
MessageManager.sendMessage(p, MessageType.NO_PERMISSION_STYLE, style.getName());
return;
}
PPlayerDataManager.getInstance().savePPlayer(p.getUniqueId(), style);
if (style != DefaultStyles.NONE) {
MessageManager.sendMessage(p, MessageType.NOW_USING_STYLE, style.getName());
} else {
MessageManager.sendMessage(p, MessageType.CLEARED_STYLE);
}
return;
}
MessageManager.sendMessage(p, MessageType.INVALID_TYPE_STYLE);
}
/**
* Called when a player uses /pp styles
*
* @param p The player who used the command
*/
private void onStyles(Player p) {
if (PermissionManager.getStylesUserHasPermissionFor(p).size() == 1) {
MessageManager.sendMessage(p, MessageType.NO_STYLES);
return;
}
String toSend = MessageType.USE.getMessage() + " ";
for (ParticleStyle style : ParticleStyleManager.getStyles()) {
if (PermissionManager.hasStylePermission(p, style)) {
toSend += style.getName();
toSend += ", ";
}
}
if (toSend.endsWith(", ")) {
toSend = toSend.substring(0, toSend.length() - 2);
}
MessageManager.sendCustomMessage(p, toSend);
MessageManager.sendCustomMessage(p, MessageType.USAGE.getMessage() + " " + MessageType.STYLE_USAGE.getMessage());
}
/**
* 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);
if (p.hasPermission("playerparticles.fixed.clear")) MessageManager.sendMessage(p, MessageType.FIXED_COMMAND_DESC_CLEAR);
return;
}
String cmd = args[0];
String[] cmdArgs = new String[args.length - 1];
for (int i = 1; i < args.length; i++) {
cmdArgs[i - 1] = args[i];
}
args = cmdArgs;
if (cmd.equalsIgnoreCase("create")) {
final String[] f_args = args;
PPlayerDataManager.getInstance().hasPlayerReachedMaxFixedEffects(p.getUniqueId(), (reachedMax) -> {
if (reachedMax) {
MessageManager.sendMessage(p, MessageType.MAX_FIXED_EFFECTS_REACHED);
return;
}
if (f_args.length < 5) {
MessageManager.sendMessage(p, MessageType.CREATE_FIXED_MISSING_ARGS, (5 - f_args.length) + "");
return;
}
double xPos = -1, yPos = -1, zPos = -1;
try {
if (f_args[0].startsWith("~")) {
if (f_args[0].equals("~")) xPos = p.getLocation().getX();
else xPos = p.getLocation().getX() + Double.parseDouble(f_args[0].substring(1));
} else {
xPos = Double.parseDouble(f_args[0]);
}
if (f_args[1].startsWith("~")) {
if (f_args[1].equals("~")) yPos = p.getLocation().getY() + 1;
else yPos = p.getLocation().getY() + 1 + Double.parseDouble(f_args[1].substring(1));
} else {
yPos = Double.parseDouble(f_args[1]);
}
if (f_args[2].startsWith("~")) {
if (f_args[2].equals("~")) zPos = p.getLocation().getZ();
else zPos = p.getLocation().getZ() + Double.parseDouble(f_args[2].substring(1));
} else {
zPos = Double.parseDouble(f_args[2]);
}
} catch (Exception e) {
MessageManager.sendMessage(p, MessageType.CREATE_FIXED_INVALID_COORDS);
return;
}
double distanceFromEffect = p.getLocation().distance(new Location(p.getWorld(), xPos, yPos, zPos));
int maxCreationDistance = PPlayerDataManager.getInstance().getMaxFixedEffectCreationDistance();
if (maxCreationDistance != 0 && distanceFromEffect > maxCreationDistance) {
MessageManager.sendMessage(p, MessageType.CREATE_FIXED_OUT_OF_RANGE, maxCreationDistance + "");
return;
}
ParticleEffect effect = ParticleManager.effectFromString(f_args[3]);
if (effect == null) {
MessageManager.sendMessage(p, MessageType.CREATE_FIXED_INVALID_EFFECT, f_args[3]);
return;
} else if (!PermissionManager.hasEffectPermission(p, effect)) {
MessageManager.sendMessage(p, MessageType.CREATE_FIXED_NO_PERMISSION_EFFECT, effect.getName());
return;
}
ParticleStyle style = ParticleStyleManager.styleFromString(f_args[4]);
if (style == null) {
MessageManager.sendMessage(p, MessageType.CREATE_FIXED_INVALID_STYLE, f_args[4]);
return;
} else if (!PermissionManager.hasStylePermission(p, style)) {
MessageManager.sendMessage(p, MessageType.CREATE_FIXED_NO_PERMISSION_STYLE, f_args[4]);
return;
}
if (!style.canBeFixed()) {
MessageManager.sendMessage(p, MessageType.CREATE_FIXED_NON_FIXABLE_STYLE, style.getName());
return;
}
ItemData itemData = null;
BlockData blockData = null;
OrdinaryColor colorData = null;
NoteColor noteColorData = null;
if (f_args.length > 5) {
if (effect.hasProperty(ParticleProperty.COLORABLE)) {
if (effect == ParticleEffect.NOTE) {
if (f_args[5].equalsIgnoreCase("rainbow")) {
noteColorData = new NoteColor(99);
} else {
int note = -1;
try {
note = Integer.parseInt(f_args[5]);
} catch (Exception e) {
MessageManager.sendMessage(p, MessageType.CREATE_FIXED_DATA_ERROR, "note");
return;
}
if (note < 0 || note > 23) {
MessageManager.sendMessage(p, MessageType.CREATE_FIXED_DATA_ERROR, "note");
return;
}
noteColorData = new NoteColor(note);
}
} else {
if (f_args[5].equalsIgnoreCase("rainbow")) {
colorData = new OrdinaryColor(999, 999, 999);
} else {
int r = -1;
int g = -1;
int b = -1;
try {
r = Integer.parseInt(f_args[5]);
g = Integer.parseInt(f_args[6]);
b = Integer.parseInt(f_args[7]);
} catch (Exception e) {
MessageManager.sendMessage(p, MessageType.CREATE_FIXED_DATA_ERROR, "color");
return;
}
if (r < 0 || r > 255 || g < 0 || g > 255 || b < 0 || b > 255) {
MessageManager.sendMessage(p, MessageType.CREATE_FIXED_DATA_ERROR, "color");
return;
}
colorData = new OrdinaryColor(r, g, b);
}
}
} else if (effect.hasProperty(ParticleProperty.REQUIRES_MATERIAL_DATA)) {
if (effect == ParticleEffect.BLOCK || effect == ParticleEffect.FALLING_DUST) {
Material material = null;
try {
material = ParticleUtils.closestMatch(f_args[5]);
if (material == null) material = Material.matchMaterial(f_args[5]);
if (material == null) throw new Exception();
} catch (Exception e) {
MessageManager.sendMessage(p, MessageType.CREATE_FIXED_DATA_ERROR, "block");
return;
}
blockData = new BlockData(material);
} else if (effect == ParticleEffect.ITEM) {
Material material = null;
try {
material = ParticleUtils.closestMatch(f_args[5]);
if (material == null) material = Material.matchMaterial(f_args[5]);
if (material == null) throw new Exception();
} catch (Exception e) {
MessageManager.sendMessage(p, MessageType.CREATE_FIXED_DATA_ERROR, "item");
return;
}
itemData = new ItemData(material);
}
}
}
// If somebody knows how to avoid this, please create a pull request
final double f_xPos = xPos, f_yPos = yPos, f_zPos = zPos;
final ItemData f_itemData = itemData;
final BlockData f_blockData = blockData;
final OrdinaryColor f_colorData = colorData;
final NoteColor f_noteData = noteColorData;
PPlayerDataManager.getInstance().getNextFixedEffectId(p.getUniqueId(), (nextFixedEffectId) -> {
FixedParticleEffect fixedEffect = new FixedParticleEffect(p.getUniqueId(), // @formatter:off
nextFixedEffectId,
p.getLocation().getWorld().getName(), f_xPos, f_yPos, f_zPos,
effect, style, f_itemData, f_blockData, f_colorData, f_noteData); // @formatter:on
MessageManager.sendMessage(p, MessageType.CREATE_FIXED_SUCCESS);
PPlayerDataManager.getInstance().saveFixedEffect(fixedEffect);
});
});
} else if (cmd.equalsIgnoreCase("remove")) {
if (args.length < 1) {
MessageManager.sendMessage(p, MessageType.REMOVE_FIXED_NO_ARGS);
return;
}
int id = -1;
try {
id = Integer.parseInt(args[0]);
} catch (Exception e) {
MessageManager.sendMessage(p, MessageType.REMOVE_FIXED_INVALID_ARGS);
return;
}
final int f_id = id;
PPlayerDataManager.getInstance().removeFixedEffect(p.getUniqueId(), id, (successful) -> {
if (successful) {
MessageManager.sendMessage(p, MessageType.REMOVE_FIXED_SUCCESS, f_id + "");
} else {
MessageManager.sendMessage(p, MessageType.REMOVE_FIXED_NONEXISTANT, f_id + "");
}
});
} else if (cmd.equalsIgnoreCase("list")) {
PPlayerDataManager.getInstance().getFixedEffectIdsForPlayer(p.getUniqueId(), (ids) -> {
Collections.sort(ids);
if (ids.isEmpty()) {
MessageManager.sendMessage(p, MessageType.LIST_FIXED_NONE);
return;
}
String msg = MessageType.LIST_FIXED_SUCCESS.getMessage();
boolean first = true;
for (int id : ids) {
if (!first) msg += ", ";
else first = false;
msg += id;
}
MessageManager.sendCustomMessage(p, msg);
});
} else if (cmd.equalsIgnoreCase("info")) {
if (args.length < 1) {
MessageManager.sendMessage(p, MessageType.INFO_FIXED_NO_ARGS);
return;
}
int id = -1;
try {
id = Integer.parseInt(args[0]);
} catch (Exception e) {
MessageManager.sendMessage(p, MessageType.INFO_FIXED_INVALID_ARGS);
return;
}
final int f_id = id;
PPlayerDataManager.getInstance().getFixedEffectForPlayerById(p.getUniqueId(), id, (fixedEffect) -> {
if (fixedEffect == null) {
MessageManager.sendMessage(p, MessageType.INFO_FIXED_NONEXISTANT, f_id + "");
return;
}
DecimalFormat df = new DecimalFormat("0.##"); // Decimal formatter so the coords aren't super long
String listMessage = MessageType.INFO_FIXED_INFO.getMessage() // @formatter:off
.replaceAll("\\{0\\}", fixedEffect.getId() + "")
.replaceAll("\\{1\\}", fixedEffect.getLocation().getWorld().getName())
.replaceAll("\\{2\\}", df.format(fixedEffect.getLocation().getX()) + "")
.replaceAll("\\{3\\}", df.format(fixedEffect.getLocation().getY()) + "")
.replaceAll("\\{4\\}", df.format(fixedEffect.getLocation().getZ()) + "")
.replaceAll("\\{5\\}", fixedEffect.getParticleEffect().getName())
.replaceAll("\\{6\\}", fixedEffect.getParticleStyle().getName())
.replaceAll("\\{7\\}", fixedEffect.getParticleDataString()); // @formatter:on
MessageManager.sendCustomMessage(p, listMessage);
});
} else if (cmd.equalsIgnoreCase("clear")) {
if (!p.hasPermission("playerparticles.fixed.clear")) {
MessageManager.sendMessage(p, MessageType.CLEAR_FIXED_NO_PERMISSION);
return;
}
if (args.length < 1) {
MessageManager.sendMessage(p, MessageType.CLEAR_FIXED_NO_ARGS);
return;
}
int radius = -1;
try {
radius = Math.abs(Integer.parseInt(args[0]));
} catch (Exception e) {
MessageManager.sendMessage(p, MessageType.CLEAR_FIXED_INVALID_ARGS);
return;
}
ArrayList<FixedParticleEffect> fixedEffectsToRemove = new ArrayList<FixedParticleEffect>();
for (FixedParticleEffect fixedEffect : ParticleManager.fixedParticleEffects)
if (fixedEffect.getLocation().getWorld() == p.getLocation().getWorld() && fixedEffect.getLocation().distance(p.getLocation()) <= radius)
fixedEffectsToRemove.add(fixedEffect);
for (FixedParticleEffect fixedEffect : fixedEffectsToRemove)
PPlayerDataManager.getInstance().removeFixedEffect(fixedEffect.getOwnerUniqueId(), fixedEffect.getId(), (successful) -> { });
String clearMessage = MessageType.CLEAR_FIXED_SUCCESS.getMessage() // @formatter:off
.replaceAll("\\{0\\}", fixedEffectsToRemove.size() + "")
.replaceAll("\\{1\\}", radius + ""); // @formatter:on
MessageManager.sendCustomMessage(p, clearMessage);
return;
} 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);
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);
}
PPlayerDataManager.getInstance().getPPlayer(p.getUniqueId(), (pplayer) -> {
PlayerParticlesGui.changeState(pplayer, GuiState.DEFAULT);
});
}
}

View file

@ -1,19 +1,9 @@
/**
* 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.
*/
/*
* TODO: v5.2
* + Command to force set an effect/style for a player
* + Tab completion for fixed effects
* TODO: v5.3 (actually v6)
* + Add new style 'tornado'
* + Add new style 'companion'
* + Add new style 'atom'
* + Add new style 'rings'
* + Add new style 'doubleorbit'
* * Adjust PParticles to use a Vector instead of a Location
* * Setting in config.yml to make non-event styles display particles using DefaultStyles.FEET while the player is moving
*/
package com.esophose.playerparticles;
@ -27,17 +17,26 @@ import org.bukkit.Bukkit;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.scheduler.BukkitRunnable;
import org.bukkit.scheduler.BukkitTask;
import com.esophose.playerparticles.gui.PlayerParticlesGui;
import com.esophose.playerparticles.manager.DatabaseManager;
import com.esophose.playerparticles.manager.MessageManager;
import com.esophose.playerparticles.command.ParticleCommandHandler;
import com.esophose.playerparticles.database.DatabaseConnector;
import com.esophose.playerparticles.database.MySqlDatabaseConnector;
import com.esophose.playerparticles.database.SqliteDatabaseConnector;
import com.esophose.playerparticles.gui.GuiHandler;
import com.esophose.playerparticles.manager.LangManager;
import com.esophose.playerparticles.manager.ParticleManager;
import com.esophose.playerparticles.manager.SettingManager;
import com.esophose.playerparticles.manager.SettingManager.PSetting;
import com.esophose.playerparticles.particles.ParticleGroup;
import com.esophose.playerparticles.styles.DefaultStyles;
import com.esophose.playerparticles.updater.PluginUpdateListener;
import com.esophose.playerparticles.updater.Updater;
public class PlayerParticles extends JavaPlugin {
private static Plugin pluginInstance;
/**
* The version a new update has, will be null if the config has it disabled
* or if there is no new version
@ -45,90 +44,53 @@ public class PlayerParticles extends JavaPlugin {
public static String updateVersion = null;
/**
* The MySQL database connection manager
* The database connection manager
*/
public static DatabaseManager mySQL = null;
private static DatabaseConnector databaseConnector = null;
/**
* Whether or not to use MySQL as determined in the config
* The task that spawns the particles
*/
public static boolean useMySQL = false;
private static BukkitTask particleTask = null;
/**
* Registers all the styles available by default
* Saves the default config if it doesn't exist
* Registers the tab completer and the event listeners
* Checks if the config needs to be updated to the new version
* Makes sure the database is accessable
* Updates the map and styleMap @see ParticleCreator
* Makes sure the database is accessible
* Starts the particle spawning task
* Registers the command executor
* Checks for any updates if checking is enabled in the config
*/
public void onEnable() {
DefaultStyles.registerStyles();
MessageManager.setup();
saveDefaultConfig();
getCommand("pp").setTabCompleter(new ParticleCommandCompleter());
getCommand("pp").setExecutor(new ParticleCommandExecutor());
pluginInstance = Bukkit.getServer().getPluginManager().getPlugin("PlayerParticles");
getCommand("pp").setTabCompleter(new ParticleCommandHandler());
getCommand("pp").setExecutor(new ParticleCommandHandler());
Bukkit.getPluginManager().registerEvents(new ParticleManager(), this);
Bukkit.getPluginManager().registerEvents(new PluginUpdateListener(), this);
Bukkit.getPluginManager().registerEvents(new PlayerParticlesGui(), this);
double configVersion = getConfig().getDouble("version");
if (configVersion < Double.parseDouble(getDescription().getVersion())) {
// Make sure database information gets carried over between config updates
boolean databaseEnable = false;
String databaseHostname = "";
int databasePort = 3306;
String databaseName = "";
String databaseUserName = "";
String databaseUserPassword = "";
Bukkit.getPluginManager().registerEvents(new GuiHandler(), this);
saveDefaultConfig();
double configVersion = PSetting.VERSION.getDouble();
boolean updatePluginSettings = configVersion < Double.parseDouble(getDescription().getVersion());
if (updatePluginSettings) {
File configFile = new File(getDataFolder(), "config.yml");
if (configFile.exists()) {
databaseEnable = getConfig().getBoolean("database-enable");
databaseHostname = getConfig().getString("database-hostname");
databasePort = getConfig().getInt("database-port");
databaseName = getConfig().getString("database-name");
databaseUserName = getConfig().getString("database-user-name");
databaseUserPassword = getConfig().getString("database-user-password");
if (databaseEnable) { // @formatter:off
getLogger().warning("== WARNING == The PlayerParticles database configuration was detected as database-enable=true. " +
"The database configuration has been loaded this time for critical schema updates, but has also been DELETED from the config.yml! " +
"This needs to be replaced or else the plugin wont connect to the database on its next load!"); // @formatter:on
}
configFile.delete();
}
saveDefaultConfig();
reloadConfig();
getConfig().set("database-enable", databaseEnable);
getConfig().set("database-hostname", databaseHostname);
getConfig().set("database-port", databasePort);
getConfig().set("database-name", databaseName);
getConfig().set("database-user-name", databaseUserName);
getConfig().set("database-user-password", databaseUserPassword);
getLogger().warning("The config.yml has been updated to v" + getDescription().getVersion() + "!");
}
if (configVersion < 5.2) {
checkDatabase(true); // @formatter:off
getLogger().warning("All previous player data has been purged. " +
"PlayerParticles v" + getDescription().getVersion() + " is not backwards compatible with the previous data schema. " +
"If you were using regular file storage, the new data file is called pplayerData.yml, the old file playerData.yml is still there. " +
"If you were using database storage, all data has been deleted."); // @formatter:on
} else {
checkDatabase(false);
}
checkDatabase(configVersion < 5.2);
startParticleTask();
if (shouldCheckUpdates()) {
if (PSetting.CHECK_UPDATES.getBoolean()) {
new BukkitRunnable() {
public void run() {
final File file = getFile();
try { // This can throw an exception if the server has no internet connection or if the Curse API is down
Updater updater = new Updater(getPlugin(), 82823, file, Updater.UpdateType.NO_DOWNLOAD, false);
Updater updater = new Updater(pluginInstance, 82823, getFile(), Updater.UpdateType.NO_DOWNLOAD, false);
if (Double.parseDouble(updater.getLatestName().replaceAll("PlayerParticles v", "")) > Double.parseDouble(getPlugin().getDescription().getVersion())) {
updateVersion = updater.getLatestName().replaceAll("PlayerParticles v", "");
getLogger().info("An update (v" + updateVersion + ") is available! You are running v" + getPlugin().getDescription().getVersion());
@ -139,17 +101,49 @@ public class PlayerParticles extends JavaPlugin {
}
}.runTaskAsynchronously(this);
}
this.reload(updatePluginSettings);
}
/**
* Clean up MySQL connection if it's open
* Clean up database connection if it's open
* Close all users with an open PlayerParticles GUI
*/
public void onDisable() {
if (useMySQL) {
mySQL.closeConnection();
databaseConnector.closeConnection();
GuiHandler.forceCloseAllOpenGUIs();
}
/**
* Reloads the settings of the plugin
*
* @param updatePluginSettings True if the settings should be updated to the latest version of the plugin
*/
public void reload(boolean updatePluginSettings) {
this.reloadConfig();
// If not null, plugin is already loaded
if (particleTask != null) {
particleTask.cancel();
particleTask = null;
databaseConnector.closeConnection();
databaseConnector = null;
GuiHandler.forceCloseAllOpenGUIs();
} else {
DefaultStyles.registerStyles(); // Only ever load styles once
}
PlayerParticlesGui.forceCloseAllOpenGUIs();
// This runs before the SettingManager is reloaded, the credentials will not be stored in memory for more than a few milliseconds
configureDatabase(PSetting.DATABASE_ENABLE.getBoolean());
SettingManager.reload();
LangManager.reload(updatePluginSettings);
ParticleGroup.reload();
GuiHandler.setup();
ParticleManager.refreshData();
startParticleTask();
}
/**
@ -158,99 +152,102 @@ public class PlayerParticles extends JavaPlugin {
* @return The PlayerParticles plugin instance
*/
public static Plugin getPlugin() {
return Bukkit.getPluginManager().getPlugin("PlayerParticles");
return pluginInstance;
}
/**
* Checks the config if the plugin can look for updates
* Gets the DatabaseConnector that allows querying the database
*
* @return True if check-updates is set to true in the config
* @return The DatabaseConnector
*/
public boolean shouldCheckUpdates() {
return getConfig().getBoolean("check-updates");
public static DatabaseConnector getDBConnector() {
return databaseConnector;
}
/**
* Checks if database-enable is true in the config, if it is then continue
* Checks if database-enable is true in the config, if it is then uses MySql
* Gets the database connection information from the config and tries to connect to the server
* Removes old table from previous versions of the plugin
* Creates new tables if they don't exist
* Sets useMySQL to true if it connects successfully, and false if it fails or isn't enabled
*
* @param useMySql If we should use MySQL as the database type, if false, uses SQLite
*/
private void checkDatabase(boolean shouldPurge) {
if (getConfig().getBoolean("database-enable")) {
mySQL = new DatabaseManager(getConfig());
useMySQL = mySQL.isInitialized(); // If something goes wrong, this will be set to false
if (!useMySQL) return; // Break out, couldn't set up the database connection
// Queries are purposely not run in an asynchronous task, this is on plugin startup and shouldn't affect the end users
mySQL.connect((connection) -> { // @formatter:off
if (shouldPurge) { // Reset the database
try (Statement statement = connection.createStatement()) {
statement.addBatch("DROP TABLE pp_users"); // Drop tables, they will be recreated from scratch
statement.addBatch("DROP TABLE pp_fixed");
statement.addBatch("DROP TABLE pp_data_item");
statement.addBatch("DROP TABLE pp_data_block");
statement.addBatch("DROP TABLE pp_data_color");
statement.addBatch("DROP TABLE pp_data_note");
} catch (SQLException e) {
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;
}
}
try (Statement statement = connection.createStatement();
ResultSet res = statement.executeQuery("SHOW TABLES LIKE 'pp_users'")) {
if (res.next()) { // Database is already created
try (Statement statement2 = connection.createStatement();
ResultSet res2 = statement2.executeQuery("SHOW TABLES LIKE 'pp_fixed'")) {
if (!res2.next()) { // Is the current database of an old version?
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);");
}
}
} else { // Database isn't created yet
mySQL.updateSQL("CREATE TABLE pp_users (player_uuid VARCHAR(36), effect VARCHAR(32), style VARCHAR(32));" +
"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));" +
"CREATE TABLE pp_data_block (uuid VARCHAR(36), material VARCHAR(32));" +
"CREATE TABLE pp_data_color (uuid VARCHAR(36), r SMALLINT, g SMALLINT, b SMALLINT);" +
"CREATE TABLE pp_data_note (uuid VARCHAR(36), note SMALLINT);");
}
} catch (SQLException e) {
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;
}
});
private void configureDatabase(boolean useMySql) {
if (useMySql) {
databaseConnector = new MySqlDatabaseConnector();
} else {
useMySQL = false;
} // @formatter:on
try {
Class.forName("org.sqlite.JDBC"); // This is required to put here for Spigot 1.9 and 1.10 for some reason
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
databaseConnector = new SqliteDatabaseConnector(this.getDataFolder().getAbsolutePath());
}
if (!databaseConnector.isInitialized()) {
getLogger().severe("Unable to connect to the MySQL database! Is your login information correct? Falling back to SQLite database instead.");
configureDatabase(false);
return;
}
databaseConnector.connect((connection) -> {
// Check if pp_users exists, if it does, this is an old database schema that needs to be deleted
try { // @formatter:off
try (Statement statement = connection.createStatement()) {
String pp_usersQuery;
if (useMySql) {
pp_usersQuery = "SHOW TABLES LIKE 'pp_users'";
} else {
pp_usersQuery = "SELECT name FROM sqlite_master WHERE type = 'table' AND name = 'pp_users'";
}
ResultSet result = statement.executeQuery(pp_usersQuery);
if (result.next()) {
statement.close();
Statement dropStatement = connection.createStatement();
dropStatement.addBatch("DROP TABLE IF EXISTS pp_users");
dropStatement.addBatch("DROP TABLE IF EXISTS pp_fixed");
dropStatement.addBatch("DROP TABLE IF EXISTS pp_data_item");
dropStatement.addBatch("DROP TABLE IF EXISTS pp_data_block");
dropStatement.addBatch("DROP TABLE IF EXISTS pp_data_color");
dropStatement.addBatch("DROP TABLE IF EXISTS pp_data_note");
dropStatement.executeBatch();
getLogger().warning("Deleted old " + (useMySql ? "MySQL" : "SQLite") + " database schema, it was out of date.");
}
}
// Try to create the tables just in case they don't exist
try (Statement createStatement = connection.createStatement()) {
createStatement.addBatch("CREATE TABLE IF NOT EXISTS pp_particle (uuid VARCHAR(36), group_uuid VARCHAR(36), id SMALLINT, effect VARCHAR(100), style VARCHAR(100), item_material VARCHAR(100), block_material VARCHAR(100), note SMALLINT, r SMALLINT, g SMALLINT, b SMALLINT, PRIMARY KEY(uuid))");
createStatement.addBatch("CREATE TABLE IF NOT EXISTS pp_group (uuid VARCHAR(36), owner_uuid VARCHAR(36), name VARCHAR(100), PRIMARY KEY(uuid))");
createStatement.addBatch("CREATE TABLE IF NOT EXISTS pp_fixed (owner_uuid VARCHAR(36), id SMALLINT, particle_uuid VARCHAR(36), world VARCHAR(100), xPos DOUBLE, yPos DOUBLE, zPos DOUBLE, PRIMARY KEY(owner_uuid, id), FOREIGN KEY(particle_uuid) REFERENCES pp_particle(uuid) ON DELETE CASCADE)");
int[] results = createStatement.executeBatch();
if (results[0] + results[1] + results[2] > 0) {
getLogger().warning("Updated " + (useMySql ? "MySQL" : "SQLite") + " database schema.");
}
}
} catch (SQLException ex) {
ex.printStackTrace();
if (useMySql) {
getLogger().severe("Unable to connect to the MySQL database! Is your login information correct? Falling back to SQLite database instead.");
configureDatabase(false);
} else {
getLogger().severe("Unable to connect to the SQLite database! This is a critical error, the plugin will be unable to save any data.");
}
}
}); // @formatter:on
}
/**
* Starts the task reponsible for spawning particles
* Starts the task responsible for spawning particles
* Run in the synchronous task so it starts after all plugins have loaded, including extensions
*/
private void startParticleTask() {
final Plugin playerParticles = this;
new BukkitRunnable() {
public void run() {
ParticleManager.refreshPPlayers(); // Add any online players who have particles
ParticleManager.addAllFixedEffects(); // Add all fixed effects
PlayerParticlesGui.setup();
long ticks = getConfig().getLong("ticks-per-particle");
new ParticleManager().runTaskTimer(playerParticles, 0, ticks);
long ticks = PSetting.TICKS_PER_PARTICLE.getLong();
particleTask = new ParticleManager().runTaskTimer(playerParticles, 5, ticks);
}
}.runTaskLater(playerParticles, 1);
}

View file

@ -0,0 +1,208 @@
package com.esophose.playerparticles.command;
import java.util.ArrayList;
import java.util.List;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.util.StringUtil;
import com.esophose.playerparticles.manager.DataManager;
import com.esophose.playerparticles.manager.LangManager;
import com.esophose.playerparticles.manager.LangManager.Lang;
import com.esophose.playerparticles.manager.PermissionManager;
import com.esophose.playerparticles.particles.PPlayer;
import com.esophose.playerparticles.particles.ParticleEffect;
import com.esophose.playerparticles.particles.ParticleEffect.NoteColor;
import com.esophose.playerparticles.particles.ParticleEffect.OrdinaryColor;
import com.esophose.playerparticles.particles.ParticleEffect.ParticleProperty;
import com.esophose.playerparticles.particles.ParticleGroup;
import com.esophose.playerparticles.particles.ParticlePair;
import com.esophose.playerparticles.styles.api.ParticleStyle;
import com.esophose.playerparticles.styles.api.ParticleStyleManager;
import com.esophose.playerparticles.util.ParticleUtils;
public class AddCommandModule implements CommandModule {
public void onCommandExecute(PPlayer pplayer, String[] args) {
if (args.length < 2) {
CommandModule.printUsage(pplayer, this);
return;
}
int maxParticlesAllowed = PermissionManager.getMaxParticlesAllowed(pplayer.getPlayer());
if (pplayer.getActiveParticles().size() >= maxParticlesAllowed) {
LangManager.sendMessage(pplayer, Lang.ADD_REACHED_MAX, maxParticlesAllowed);
return;
}
ParticleEffect effect = ParticleEffect.fromName(args[0]);
if (effect == null) {
LangManager.sendMessage(pplayer, Lang.EFFECT_INVALID, args[0]);
return;
} else if (!PermissionManager.hasEffectPermission(pplayer.getPlayer(), effect)) {
LangManager.sendMessage(pplayer, Lang.EFFECT_NO_PERMISSION, effect.getName());
return;
}
ParticleStyle style = ParticleStyle.fromName(args[1]);
if (style == null) {
LangManager.sendMessage(pplayer, Lang.STYLE_INVALID, args[1]);
return;
} else if (!PermissionManager.hasStylePermission(pplayer.getPlayer(), style)) {
LangManager.sendMessage(pplayer, Lang.STYLE_NO_PERMISSION, args[1]);
return;
}
Material itemData = null;
Material blockData = null;
OrdinaryColor colorData = null;
NoteColor noteColorData = null;
if (args.length > 2) {
if (effect.hasProperty(ParticleProperty.COLORABLE)) {
if (effect == ParticleEffect.NOTE) {
if (args[2].equalsIgnoreCase("rainbow")) {
noteColorData = new NoteColor(99);
} else if (args[2].equalsIgnoreCase("random")) {
noteColorData = new NoteColor(98);
} else {
int note = -1;
try {
note = Integer.parseInt(args[2]);
} catch (Exception e) {
LangManager.sendMessage(pplayer, Lang.DATA_INVALID_NOTE);
return;
}
if (note < 0 || note > 24) {
LangManager.sendMessage(pplayer, Lang.DATA_INVALID_NOTE);
return;
}
noteColorData = new NoteColor(note);
}
} else {
if (args[2].equalsIgnoreCase("rainbow")) {
colorData = new OrdinaryColor(999, 999, 999);
} else if (args[2].equalsIgnoreCase("random")) {
colorData = new OrdinaryColor(998, 998, 998);
} else {
int r = -1;
int g = -1;
int b = -1;
try {
r = Integer.parseInt(args[2]);
g = Integer.parseInt(args[3]);
b = Integer.parseInt(args[4]);
} catch (Exception e) {
LangManager.sendMessage(pplayer, Lang.DATA_INVALID_COLOR);
return;
}
if (r < 0 || r > 255 || g < 0 || g > 255 || b < 0 || b > 255) {
LangManager.sendMessage(pplayer, Lang.DATA_INVALID_COLOR);
return;
}
colorData = new OrdinaryColor(r, g, b);
}
}
} else if (effect.hasProperty(ParticleProperty.REQUIRES_MATERIAL_DATA)) {
if (effect == ParticleEffect.BLOCK || effect == ParticleEffect.FALLING_DUST) {
try {
blockData = ParticleUtils.closestMatch(args[2]);
if (blockData == null || !blockData.isBlock()) throw new Exception();
} catch (Exception e) {
LangManager.sendMessage(pplayer, Lang.DATA_INVALID_BLOCK);
return;
}
} else if (effect == ParticleEffect.ITEM) {
try {
itemData = ParticleUtils.closestMatch(args[2]);
if (itemData == null || itemData.isBlock()) throw new Exception();
} catch (Exception e) {
LangManager.sendMessage(pplayer, Lang.DATA_INVALID_ITEM);
return;
}
}
}
}
ParticleGroup group = pplayer.getActiveParticleGroup();
ParticlePair newParticle = new ParticlePair(pplayer.getUniqueId(), pplayer.getNextActiveParticleId(), effect, style, blockData, blockData, colorData, noteColorData);
group.getParticles().add(newParticle);
DataManager.saveParticleGroup(pplayer.getUniqueId(), group);
LangManager.sendMessage(pplayer, Lang.ADD_PARTICLE_APPLIED, newParticle.getEffect().getName(), newParticle.getStyle().getName(), newParticle.getDataString());
if (ParticleStyleManager.isCustomHandled(newParticle.getStyle())) {
LangManager.sendMessage(pplayer, Lang.STYLE_EVENT_SPAWNING_INFO, newParticle.getStyle().getName());
}
}
public List<String> onTabComplete(PPlayer pplayer, String[] args) {
Player p = pplayer.getPlayer();
List<String> matches = new ArrayList<String>();
if (args.length <= 1) { // Effect name
if (args.length == 0) matches = PermissionManager.getEffectNamesUserHasPermissionFor(p);
else StringUtil.copyPartialMatches(args[0], PermissionManager.getEffectNamesUserHasPermissionFor(p), matches);
} else if (args.length == 2) { // Style name
StringUtil.copyPartialMatches(args[1], PermissionManager.getStyleNamesUserHasPermissionFor(p), matches);
} else if (args.length >= 3) { // Data
ParticleEffect effect = ParticleEffect.fromName(args[0]);
if (effect != null) {
if (effect.hasProperty(ParticleProperty.COLORABLE)) {
List<String> possibleValues = new ArrayList<String>();
if (effect == ParticleEffect.NOTE) { // Note data
if (args.length == 3) {
possibleValues.add("<0-24>");
possibleValues.add("rainbow");
possibleValues.add("random");
}
} else { // Color data
if (args.length <= 5 && !args[2].equalsIgnoreCase("rainbow") && !args[2].equalsIgnoreCase("random")) {
possibleValues.add("<0-255>");
}
if (args.length <= 4 && !args[2].equalsIgnoreCase("rainbow") && !args[2].equalsIgnoreCase("random")) {
possibleValues.add("<0-255> <0-255>");
}
if (args.length <= 3) {
possibleValues.add("<0-255> <0-255> <0-255>");
possibleValues.add("rainbow");
possibleValues.add("random");
}
}
StringUtil.copyPartialMatches(args[args.length - 1], possibleValues, matches);
} else if (args.length == 3 && effect.hasProperty(ParticleProperty.REQUIRES_MATERIAL_DATA)) {
if (effect == ParticleEffect.BLOCK || effect == ParticleEffect.FALLING_DUST) { // Block material
matches = StringUtil.copyPartialMatches(args[2], ParticleUtils.getAllBlockMaterials(), matches);
} else if (effect == ParticleEffect.ITEM) { // Item material
matches = StringUtil.copyPartialMatches(args[2], ParticleUtils.getAllItemMaterials(), matches);
}
}
}
}
return matches;
}
public String getName() {
return "add";
}
public Lang getDescription() {
return Lang.COMMAND_DESCRIPTION_ADD;
}
public String getArguments() {
return "<effect> <style> [data]";
}
public boolean requiresEffects() {
return true;
}
}

View file

@ -0,0 +1,86 @@
package com.esophose.playerparticles.command;
import java.text.MessageFormat;
import java.util.List;
import com.esophose.playerparticles.manager.LangManager;
import com.esophose.playerparticles.manager.LangManager.Lang;
import com.esophose.playerparticles.particles.PPlayer;
import net.md_5.bungee.api.ChatColor;
public interface CommandModule {
/**
* Called when this command gets executed
*
* @param pplayer The PPlayer who executed this command
* @param args The arguments to this command
*/
public void onCommandExecute(PPlayer pplayer, String[] args);
/**
* Called when a player tries to tab complete this command
*
* @param pplayer The PPlayer who is tab completing this command
* @param args Arguments typed so far
* @return A list of possible argument values
*/
public List<String> onTabComplete(PPlayer pplayer, String[] args);
/**
* Gets the name of this command
*
* @return The name of this command
*/
public String getName();
/**
* Gets the Lang description of this command
*
* @return The description of this command
*/
public Lang getDescription();
/**
* Gets any arguments this command has
*
* @return The arguments this command has
*/
public String getArguments();
/**
* True if this command requires the player to have any effects
*
* @return If the player must have effects to use this command
*/
public boolean requiresEffects();
/**
* Displays a command's usage to the player
*
* @param pplayer The PPlayer to display the command usage to
* @param command The command to display usage for
*/
public static void printUsage(PPlayer pplayer, CommandModule command) {
Object[] args = new Object[] { command.getName(), command.getArguments() };
LangManager.sendCustomMessage(pplayer, new MessageFormat(ChatColor.YELLOW + "/pp {0} {1}").format(args));
}
/**
* Displays a command's usage (with its description) to the player
*
* @param pplayer The PPlayer to display the command usage to
* @param command The command to display usage for
*/
public static void printUsageWithDescription(PPlayer pplayer, CommandModule command) {
if (command.getArguments().length() == 0) {
Object[] args = new Object[] { command.getName(), LangManager.getText(command.getDescription()) };
LangManager.sendCustomMessage(pplayer, new MessageFormat(ChatColor.YELLOW + "/pp {0} - {1}").format(args));
} else {
Object[] args = new Object[] { command.getName(), command.getArguments(), LangManager.getText(command.getDescription()) };
LangManager.sendCustomMessage(pplayer, new MessageFormat(ChatColor.YELLOW + "/pp {0} {1} - {2}").format(args));
}
}
}

View file

@ -0,0 +1,70 @@
package com.esophose.playerparticles.command;
import java.util.ArrayList;
import java.util.List;
import org.bukkit.util.StringUtil;
import com.esophose.playerparticles.manager.LangManager;
import com.esophose.playerparticles.manager.LangManager.Lang;
import com.esophose.playerparticles.manager.PermissionManager;
import com.esophose.playerparticles.particles.PPlayer;
import com.esophose.playerparticles.particles.ParticleEffect;
import com.esophose.playerparticles.particles.ParticleEffect.ParticleProperty;
public class DataCommandModule implements CommandModule {
public void onCommandExecute(PPlayer pplayer, String[] args) {
if (args.length > 0) {
ParticleEffect effect = ParticleEffect.fromName(args[0]);
if (effect == null) {
LangManager.sendMessage(pplayer, Lang.EFFECT_INVALID, args[0]);
return;
}
if (effect.hasProperty(ParticleProperty.COLORABLE)) {
if (effect == ParticleEffect.NOTE) {
LangManager.sendMessage(pplayer, Lang.DATA_USAGE_NOTE, effect.getName());
} else {
LangManager.sendMessage(pplayer, Lang.DATA_USAGE_COLOR, effect.getName());
}
} else if (effect.hasProperty(ParticleProperty.REQUIRES_MATERIAL_DATA)) {
if (effect == ParticleEffect.ITEM) {
LangManager.sendMessage(pplayer, Lang.DATA_USAGE_ITEM, effect.getName());
} else {
LangManager.sendMessage(pplayer, Lang.DATA_USAGE_BLOCK, effect.getName());
}
} else {
LangManager.sendMessage(pplayer, Lang.DATA_USAGE_NONE, effect.getName());
}
} else {
LangManager.sendMessage(pplayer, Lang.DATA_NO_ARGS);
}
}
public List<String> onTabComplete(PPlayer pplayer, String[] args) {
List<String> matches = new ArrayList<String>();
if (args.length <= 1) {
if (args.length == 0) matches = PermissionManager.getEffectNamesUserHasPermissionFor(pplayer.getPlayer());
else StringUtil.copyPartialMatches(args[0], PermissionManager.getEffectNamesUserHasPermissionFor(pplayer.getPlayer()), matches);
}
return matches;
}
public String getName() {
return "data";
}
public Lang getDescription() {
return Lang.COMMAND_DESCRIPTION_DATA;
}
public String getArguments() {
return "<effect>";
}
public boolean requiresEffects() {
return true;
}
}

View file

@ -0,0 +1,45 @@
package com.esophose.playerparticles.command;
import java.util.ArrayList;
import java.util.List;
import org.bukkit.util.StringUtil;
import com.esophose.playerparticles.manager.LangManager.Lang;
import com.esophose.playerparticles.particles.PPlayer;
public class DefaultCommandModule implements CommandModule {
public void onCommandExecute(PPlayer pplayer, String[] args) {
// The default command just opens the GUI, execute the GUICommandModule
ParticleCommandHandler.findMatchingCommand("gui").onCommandExecute(pplayer, new String[] { "_byDefault_" });
}
public List<String> onTabComplete(PPlayer pplayer, String[] args) {
List<String> matches = new ArrayList<String>();
List<String> commandNames = ParticleCommandHandler.getCommandNames();
if (args.length == 0) return commandNames;
StringUtil.copyPartialMatches(args[0], commandNames, matches);
return matches;
}
public String getName() {
return "";
}
public Lang getDescription() {
return Lang.COMMAND_DESCRIPTION_DEFAULT;
}
public String getArguments() {
return "";
}
public boolean requiresEffects() {
return true;
}
}

View file

@ -0,0 +1,321 @@
package com.esophose.playerparticles.command;
import java.util.ArrayList;
import java.util.List;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.util.StringUtil;
import com.esophose.playerparticles.manager.DataManager;
import com.esophose.playerparticles.manager.LangManager;
import com.esophose.playerparticles.manager.PermissionManager;
import com.esophose.playerparticles.manager.LangManager.Lang;
import com.esophose.playerparticles.particles.PPlayer;
import com.esophose.playerparticles.particles.ParticleEffect;
import com.esophose.playerparticles.particles.ParticleGroup;
import com.esophose.playerparticles.particles.ParticlePair;
import com.esophose.playerparticles.particles.ParticleEffect.NoteColor;
import com.esophose.playerparticles.particles.ParticleEffect.OrdinaryColor;
import com.esophose.playerparticles.particles.ParticleEffect.ParticleProperty;
import com.esophose.playerparticles.styles.api.ParticleStyle;
import com.esophose.playerparticles.util.ParticleUtils;
public class EditCommandModule implements CommandModule {
public void onCommandExecute(PPlayer pplayer, String[] args) {
if (args.length < 3) {
CommandModule.printUsage(pplayer, this);
return;
}
int id = -1;
try {
id = Integer.parseInt(args[0]);
} catch (Exception e) {
LangManager.sendMessage(pplayer, Lang.ID_INVALID);
return;
}
if (id <= 0) {
LangManager.sendMessage(pplayer, Lang.ID_INVALID);
return;
}
if (pplayer.getActiveParticle(id) == null) {
LangManager.sendMessage(pplayer, Lang.ID_UNKNOWN, id);
return;
}
String[] cmdArgs = new String[args.length - 2];
for (int i = 2; i < args.length; i++) {
cmdArgs[i - 2] = args[i];
}
switch (args[1].toLowerCase()) {
case "effect":
editEffect(pplayer, id, cmdArgs);
break;
case "style":
editStyle(pplayer, id, cmdArgs);
break;
case "data":
editData(pplayer, id, cmdArgs);
break;
default:
LangManager.sendMessage(pplayer, Lang.EDIT_INVALID_PROPERTY, args[1]);
break;
}
}
/**
* Executes the effect subcommand
*
* @param pplayer The PPlayer executing the command
* @param id The target particle ID
* @param args The rest of the args
*/
private void editEffect(PPlayer pplayer, int id, String[] args) {
ParticleEffect effect = ParticleEffect.fromName(args[0]);
if (effect == null) {
LangManager.sendMessage(pplayer, Lang.EFFECT_INVALID, args[0]);
return;
} else if (!PermissionManager.hasEffectPermission(pplayer.getPlayer(), effect)) {
LangManager.sendMessage(pplayer, Lang.EFFECT_NO_PERMISSION, effect.getName());
return;
}
ParticleGroup group = pplayer.getActiveParticleGroup();
for (ParticlePair particle : group.getParticles()) {
if (particle.getId() == id) {
particle.setEffect(effect);
break;
}
}
DataManager.saveParticleGroup(pplayer.getUniqueId(), group);
LangManager.sendMessage(pplayer, Lang.EDIT_SUCCESS_EFFECT, id, effect.getName());
}
/**
* Executes the style subcommand
*
* @param pplayer The PPlayer executing the command
* @param id The target particle ID
* @param args The rest of the args
*/
private void editStyle(PPlayer pplayer, int id, String[] args) {
ParticleStyle style = ParticleStyle.fromName(args[0]);
if (style == null) {
LangManager.sendMessage(pplayer, Lang.STYLE_INVALID, args[0]);
return;
} else if (!PermissionManager.hasStylePermission(pplayer.getPlayer(), style)) {
LangManager.sendMessage(pplayer, Lang.STYLE_NO_PERMISSION, style.getName());
return;
}
ParticleGroup group = pplayer.getActiveParticleGroup();
for (ParticlePair particle : group.getParticles()) {
if (particle.getId() == id) {
particle.setStyle(style);
break;
}
}
DataManager.saveParticleGroup(pplayer.getUniqueId(), group);
LangManager.sendMessage(pplayer, Lang.EDIT_SUCCESS_STYLE, id, style.getName());
}
/**
* Executes the data subcommand
*
* @param pplayer The PPlayer executing the command
* @param id The target particle ID
* @param args The rest of the args
*/
private void editData(PPlayer pplayer, int id, String[] args) {
Material itemData = null;
Material blockData = null;
OrdinaryColor colorData = null;
NoteColor noteColorData = null;
ParticleEffect effect = pplayer.getActiveParticle(id).getEffect();
if (effect.hasProperty(ParticleProperty.COLORABLE)) {
if (effect == ParticleEffect.NOTE) {
if (args[0].equalsIgnoreCase("rainbow")) {
noteColorData = new NoteColor(99);
} else if (args[0].equalsIgnoreCase("random")) {
noteColorData = new NoteColor(98);
} else {
int note = -1;
try {
note = Integer.parseInt(args[0]);
} catch (Exception e) {
LangManager.sendMessage(pplayer, Lang.DATA_INVALID_NOTE);
return;
}
if (note < 0 || note > 24) {
LangManager.sendMessage(pplayer, Lang.DATA_INVALID_NOTE);
return;
}
noteColorData = new NoteColor(note);
}
} else {
if (args[0].equalsIgnoreCase("rainbow")) {
colorData = new OrdinaryColor(999, 999, 999);
} else if (args[0].equalsIgnoreCase("random")) {
colorData = new OrdinaryColor(998, 998, 998);
} else {
int r = -1;
int g = -1;
int b = -1;
try {
r = Integer.parseInt(args[0]);
g = Integer.parseInt(args[1]);
b = Integer.parseInt(args[2]);
} catch (Exception e) {
LangManager.sendMessage(pplayer, Lang.DATA_INVALID_COLOR);
return;
}
if (r < 0 || r > 255 || g < 0 || g > 255 || b < 0 || b > 255) {
LangManager.sendMessage(pplayer, Lang.DATA_INVALID_COLOR);
return;
}
colorData = new OrdinaryColor(r, g, b);
}
}
} else if (effect.hasProperty(ParticleProperty.REQUIRES_MATERIAL_DATA)) {
if (effect == ParticleEffect.BLOCK || effect == ParticleEffect.FALLING_DUST) {
try {
blockData = ParticleUtils.closestMatch(args[0]);
if (blockData == null || !blockData.isBlock()) throw new Exception();
} catch (Exception e) {
LangManager.sendMessage(pplayer, Lang.DATA_INVALID_BLOCK);
return;
}
} else if (effect == ParticleEffect.ITEM) {
try {
itemData = ParticleUtils.closestMatch(args[0]);
if (itemData == null || itemData.isBlock()) throw new Exception();
} catch (Exception e) {
LangManager.sendMessage(pplayer, Lang.DATA_INVALID_ITEM);
return;
}
}
}
String updatedDataString = null;
ParticleGroup group = pplayer.getActiveParticleGroup();
for (ParticlePair particle : group.getParticles()) {
if (particle.getId() == id) {
if (itemData != null) particle.setItemMaterial(itemData);
if (blockData != null) particle.setBlockMaterial(blockData);
if (colorData != null) particle.setColor(colorData);
if (noteColorData != null) particle.setNoteColor(noteColorData);
updatedDataString = particle.getDataString();
break;
}
}
DataManager.saveParticleGroup(pplayer.getUniqueId(), group);
LangManager.sendMessage(pplayer, Lang.EDIT_SUCCESS_DATA, id, updatedDataString);
}
public List<String> onTabComplete(PPlayer pplayer, String[] args) {
Player p = pplayer.getPlayer();
List<String> matches = new ArrayList<String>();
List<String> ids = new ArrayList<String>();
for (ParticlePair particles : pplayer.getActiveParticles())
ids.add(String.valueOf(particles.getId()));
if (args.length == 0) {
matches = ids;
} else if (args.length == 1) {
StringUtil.copyPartialMatches(args[0], ids, matches);
}
int id = -1;
try {
id = Integer.parseInt(args[0]);
} catch (Exception e) { }
if (pplayer.getActiveParticle(id) != null) {
if (args.length == 2) {
List<String> possibleValues = new ArrayList<String>();
possibleValues.add("effect");
possibleValues.add("style");
possibleValues.add("data");
StringUtil.copyPartialMatches(args[1], possibleValues, matches);
} else if (args.length >= 3) {
switch (args[1].toLowerCase()) {
case "effect":
if (args.length == 3)
StringUtil.copyPartialMatches(args[2], PermissionManager.getEffectNamesUserHasPermissionFor(p), matches);
break;
case "style":
if (args.length == 3)
StringUtil.copyPartialMatches(args[2], PermissionManager.getStyleNamesUserHasPermissionFor(p), matches);
break;
case "data":
ParticleEffect effect = pplayer.getActiveParticle(id).getEffect();
if (effect.hasProperty(ParticleProperty.COLORABLE)) {
List<String> possibleValues = new ArrayList<String>();
if (effect == ParticleEffect.NOTE) { // Note data
if (args.length == 3) {
possibleValues.add("<0-24>");
possibleValues.add("rainbow");
possibleValues.add("random");
}
} else { // Color data
if (args.length <= 5 && !args[2].equalsIgnoreCase("rainbow") && !args[2].equalsIgnoreCase("random")) {
possibleValues.add("<0-255>");
}
if (args.length <= 4 && !args[2].equalsIgnoreCase("rainbow") && !args[2].equalsIgnoreCase("random")) {
possibleValues.add("<0-255> <0-255>");
}
if (args.length <= 3) {
possibleValues.add("<0-255> <0-255> <0-255>");
possibleValues.add("rainbow");
possibleValues.add("random");
}
}
StringUtil.copyPartialMatches(args[args.length - 1], possibleValues, matches);
} else if (args.length == 3 && effect.hasProperty(ParticleProperty.REQUIRES_MATERIAL_DATA)) {
if (effect == ParticleEffect.BLOCK || effect == ParticleEffect.FALLING_DUST) { // Block material
matches = StringUtil.copyPartialMatches(args[2], ParticleUtils.getAllBlockMaterials(), matches);
} else if (effect == ParticleEffect.ITEM) { // Item material
matches = StringUtil.copyPartialMatches(args[2], ParticleUtils.getAllItemMaterials(), matches);
}
}
break;
}
}
}
return matches;
}
public String getName() {
return "edit";
}
public Lang getDescription() {
return Lang.COMMAND_DESCRIPTION_EDIT;
}
public String getArguments() {
return "<id> <effect>|<style>|<data> <args>";
}
public boolean requiresEffects() {
return true;
}
}

View file

@ -0,0 +1,36 @@
package com.esophose.playerparticles.command;
import java.util.ArrayList;
import java.util.List;
import com.esophose.playerparticles.manager.LangManager;
import com.esophose.playerparticles.manager.LangManager.Lang;
import com.esophose.playerparticles.particles.PPlayer;
public class EffectCommandModule implements CommandModule {
public void onCommandExecute(PPlayer pplayer, String[] args) {
LangManager.sendMessage(pplayer, Lang.COMMAND_DESCRIPTION_EFFECT);
}
public List<String> onTabComplete(PPlayer pplayer, String[] args) {
return new ArrayList<String>();
}
public String getName() {
return "effect";
}
public Lang getDescription() {
return Lang.COMMAND_DESCRIPTION_EFFECT;
}
public String getArguments() {
return "";
}
public boolean requiresEffects() {
return true;
}
}

View file

@ -0,0 +1,56 @@
package com.esophose.playerparticles.command;
import java.util.ArrayList;
import java.util.List;
import org.bukkit.entity.Player;
import com.esophose.playerparticles.manager.LangManager;
import com.esophose.playerparticles.manager.LangManager.Lang;
import com.esophose.playerparticles.manager.PermissionManager;
import com.esophose.playerparticles.particles.PPlayer;
public class EffectsCommandModule implements CommandModule {
public void onCommandExecute(PPlayer pplayer, String[] args) {
Player p = pplayer.getPlayer();
List<String> effectList = PermissionManager.getEffectNamesUserHasPermissionFor(p);
if (effectList.isEmpty()) {
LangManager.sendMessage(p, Lang.EFFECT_LIST_EMPTY);
return;
}
String toSend = "";
for (String name : effectList) {
toSend += name + ", ";
}
if (toSend.endsWith(", ")) {
toSend = toSend.substring(0, toSend.length() - 2);
}
LangManager.sendMessage(p, Lang.EFFECT_LIST, toSend);
}
public List<String> onTabComplete(PPlayer pplayer, String[] args) {
return new ArrayList<String>();
}
public String getName() {
return "effects";
}
public Lang getDescription() {
return Lang.COMMAND_DESCRIPTION_EFFECTS;
}
public String getArguments() {
return "";
}
public boolean requiresEffects() {
return false;
}
}

View file

@ -0,0 +1,797 @@
package com.esophose.playerparticles.command;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import org.bukkit.util.StringUtil;
import com.esophose.playerparticles.manager.DataManager;
import com.esophose.playerparticles.manager.LangManager;
import com.esophose.playerparticles.manager.LangManager.Lang;
import com.esophose.playerparticles.manager.ParticleManager;
import com.esophose.playerparticles.manager.PermissionManager;
import com.esophose.playerparticles.particles.FixedParticleEffect;
import com.esophose.playerparticles.particles.PPlayer;
import com.esophose.playerparticles.particles.ParticleEffect;
import com.esophose.playerparticles.particles.ParticleEffect.NoteColor;
import com.esophose.playerparticles.particles.ParticleEffect.OrdinaryColor;
import com.esophose.playerparticles.particles.ParticleEffect.ParticleProperty;
import com.esophose.playerparticles.particles.ParticlePair;
import com.esophose.playerparticles.styles.api.ParticleStyle;
import com.esophose.playerparticles.util.ParticleUtils;
public class FixedCommandModule implements CommandModule {
public void onCommandExecute(PPlayer pplayer, String[] args) {
Player p = pplayer.getPlayer();
if (!PermissionManager.canUseFixedEffects(p)) {
LangManager.sendMessage(p, Lang.FIXED_NO_PERMISSION);
return;
}
if (args.length == 0) { // General information on command
LangManager.sendMessage(p, Lang.COMMAND_DESCRIPTION_FIXED_CREATE);
LangManager.sendMessage(p, Lang.COMMAND_DESCRIPTION_FIXED_EDIT);
LangManager.sendMessage(p, Lang.COMMAND_DESCRIPTION_FIXED_REMOVE);
LangManager.sendMessage(p, Lang.COMMAND_DESCRIPTION_FIXED_LIST);
LangManager.sendMessage(p, Lang.COMMAND_DESCRIPTION_FIXED_INFO);
LangManager.sendMessage(p, Lang.COMMAND_DESCRIPTION_FIXED_CLEAR);
return;
}
String cmd = args[0];
String[] cmdArgs = new String[args.length - 1];
for (int i = 1; i < args.length; i++) {
cmdArgs[i - 1] = args[i];
}
switch (cmd.toLowerCase()) {
case "create":
handleCreate(pplayer, p, cmdArgs);
return;
case "edit":
handleEdit(pplayer, p, cmdArgs);
return;
case "remove":
handleRemove(pplayer, p, cmdArgs);
return;
case "list":
handleList(pplayer, p, cmdArgs);
return;
case "info":
handleInfo(pplayer, p, cmdArgs);
return;
case "clear":
handleClear(pplayer, p, cmdArgs);
return;
default:
LangManager.sendMessage(p, Lang.FIXED_INVALID_COMMAND);
LangManager.sendMessage(p, Lang.COMMAND_DESCRIPTION_FIXED_CREATE);
LangManager.sendMessage(p, Lang.COMMAND_DESCRIPTION_FIXED_EDIT);
LangManager.sendMessage(p, Lang.COMMAND_DESCRIPTION_FIXED_REMOVE);
LangManager.sendMessage(p, Lang.COMMAND_DESCRIPTION_FIXED_LIST);
LangManager.sendMessage(p, Lang.COMMAND_DESCRIPTION_FIXED_INFO);
LangManager.sendMessage(p, Lang.COMMAND_DESCRIPTION_FIXED_CLEAR);
}
}
/**
* Handles the command /pp fixed create
*
* @param pplayer The PPlayer
* @param p The Player
* @param args The command arguments
*/
private void handleCreate(PPlayer pplayer, Player p, String[] args) {
boolean reachedMax = PermissionManager.hasPlayerReachedMaxFixedEffects(pplayer);
if (reachedMax) {
LangManager.sendMessage(p, Lang.FIXED_MAX_REACHED);
return;
}
if (args.length < 5 && !(args.length > 0 && args[0].equalsIgnoreCase("looking") && args.length >= 3)) {
LangManager.sendMessage(p, Lang.FIXED_CREATE_MISSING_ARGS, 5 - args.length);
return;
}
double xPos = -1, yPos = -1, zPos = -1;
if (args[0].equalsIgnoreCase("looking")) {
Block targetBlock = p.getTargetBlock((Set<Material>)null, 8);
int maxDistanceSqrd = 6 * 6;
if (targetBlock.getLocation().distanceSquared(p.getLocation()) > maxDistanceSqrd) {
LangManager.sendMessage(p, Lang.FIXED_CREATE_LOOKING_TOO_FAR);
return;
}
Location blockLocation = targetBlock.getLocation().clone().add(0.5, 0.5, 0.5); // Center of block
xPos = blockLocation.getX();
yPos = blockLocation.getY();
zPos = blockLocation.getZ();
// Pad the args with the coordinates so we don't have to adjust all the indices
String[] paddedArgs = new String[args.length + 2];
paddedArgs[0] = String.valueOf(xPos);
paddedArgs[1] = String.valueOf(yPos);
paddedArgs[2] = String.valueOf(zPos);
for (int i = 1; i < args.length; i++)
paddedArgs[i + 2] = args[i];
args = paddedArgs;
} else {
try {
if (args[0].startsWith("~")) {
if (args[0].equals("~")) xPos = p.getLocation().getX();
else xPos = p.getLocation().getX() + Double.parseDouble(args[0].substring(1));
} else {
xPos = Double.parseDouble(args[0]);
}
if (args[1].startsWith("~")) {
if (args[1].equals("~")) yPos = p.getLocation().getY() + 1;
else yPos = p.getLocation().getY() + 1 + Double.parseDouble(args[1].substring(1));
} else {
yPos = Double.parseDouble(args[1]);
}
if (args[2].startsWith("~")) {
if (args[2].equals("~")) zPos = p.getLocation().getZ();
else zPos = p.getLocation().getZ() + Double.parseDouble(args[2].substring(1));
} else {
zPos = Double.parseDouble(args[2]);
}
} catch (Exception e) {
LangManager.sendMessage(p, Lang.FIXED_CREATE_INVALID_COORDS);
return;
}
}
double distanceFromEffect = p.getLocation().distance(new Location(p.getWorld(), xPos, yPos, zPos));
int maxCreationDistance = PermissionManager.getMaxFixedEffectCreationDistance();
if (maxCreationDistance != 0 && distanceFromEffect > maxCreationDistance) {
LangManager.sendMessage(p, Lang.FIXED_CREATE_OUT_OF_RANGE, maxCreationDistance);
return;
}
ParticleEffect effect = ParticleEffect.fromName(args[3]);
if (effect == null) {
LangManager.sendMessage(p, Lang.FIXED_CREATE_EFFECT_INVALID, args[3]);
return;
} else if (!PermissionManager.hasEffectPermission(p, effect)) {
LangManager.sendMessage(p, Lang.FIXED_CREATE_EFFECT_NO_PERMISSION, effect.getName());
return;
}
ParticleStyle style = ParticleStyle.fromName(args[4]);
if (style == null) {
LangManager.sendMessage(p, Lang.FIXED_CREATE_STYLE_INVALID, args[4]);
return;
} else if (!PermissionManager.hasStylePermission(p, style)) {
LangManager.sendMessage(p, Lang.FIXED_CREATE_STYLE_NO_PERMISSION, args[4]);
return;
}
if (!style.canBeFixed()) {
LangManager.sendMessage(p, Lang.FIXED_CREATE_STYLE_NON_FIXABLE, style.getName());
return;
}
Material itemData = null;
Material blockData = null;
OrdinaryColor colorData = null;
NoteColor noteColorData = null;
if (args.length > 5) {
if (effect.hasProperty(ParticleProperty.COLORABLE)) {
if (effect == ParticleEffect.NOTE) {
if (args[5].equalsIgnoreCase("rainbow")) {
noteColorData = new NoteColor(99);
} else if (args[5].equalsIgnoreCase("random")) {
noteColorData = new NoteColor(98);
} else {
int note = -1;
try {
note = Integer.parseInt(args[5]);
} catch (Exception e) {
LangManager.sendMessage(p, Lang.FIXED_CREATE_DATA_ERROR);
return;
}
if (note < 0 || note > 24) {
LangManager.sendMessage(p, Lang.FIXED_CREATE_DATA_ERROR);
return;
}
noteColorData = new NoteColor(note);
}
} else {
if (args[5].equalsIgnoreCase("rainbow")) {
colorData = new OrdinaryColor(999, 999, 999);
} else if (args[5].equalsIgnoreCase("random")) {
colorData = new OrdinaryColor(998, 998, 998);
} else {
int r = -1;
int g = -1;
int b = -1;
try {
r = Integer.parseInt(args[5]);
g = Integer.parseInt(args[6]);
b = Integer.parseInt(args[7]);
} catch (Exception e) {
LangManager.sendMessage(p, Lang.FIXED_CREATE_DATA_ERROR);
return;
}
if (r < 0 || r > 255 || g < 0 || g > 255 || b < 0 || b > 255) {
LangManager.sendMessage(p, Lang.FIXED_CREATE_DATA_ERROR);
return;
}
colorData = new OrdinaryColor(r, g, b);
}
}
} else if (effect.hasProperty(ParticleProperty.REQUIRES_MATERIAL_DATA)) {
if (effect == ParticleEffect.BLOCK || effect == ParticleEffect.FALLING_DUST) {
Material material = null;
try {
material = ParticleUtils.closestMatch(args[5]);
if (material == null) material = Material.matchMaterial(args[5]);
if (material == null || !material.isBlock()) throw new Exception();
} catch (Exception e) {
LangManager.sendMessage(p, Lang.FIXED_CREATE_DATA_ERROR);
return;
}
blockData = material;
} else if (effect == ParticleEffect.ITEM) {
Material material = null;
try {
material = ParticleUtils.closestMatch(args[5]);
if (material == null) material = Material.matchMaterial(args[5]);
if (material == null || material.isBlock()) throw new Exception();
} catch (Exception e) {
LangManager.sendMessage(p, Lang.FIXED_CREATE_DATA_ERROR);
return;
}
itemData = material;
}
}
}
int nextFixedEffectId = pplayer.getNextFixedEffectId();
ParticlePair particle = new ParticlePair(pplayer.getUniqueId(), nextFixedEffectId, effect, style, itemData, blockData, colorData, noteColorData);
FixedParticleEffect fixedEffect = new FixedParticleEffect(p.getUniqueId(), nextFixedEffectId, p.getLocation().getWorld().getName(), xPos, yPos, zPos, particle);
LangManager.sendMessage(p, Lang.FIXED_CREATE_SUCCESS);
DataManager.saveFixedEffect(fixedEffect);
}
/**
* Handles the command /pp fixed edit
*
* @param pplayer The PPlayer
* @param p The Player
* @param args The command arguments
*/
private void handleEdit(PPlayer pplayer, Player p, String[] args) {
if (args.length < 3) {
LangManager.sendMessage(p, Lang.FIXED_EDIT_MISSING_ARGS);
return;
}
int id = -1;
try {
id = Integer.parseInt(args[0]);
} catch (Exception ex) {
LangManager.sendMessage(p, Lang.FIXED_EDIT_INVALID_ID);
return;
}
FixedParticleEffect fixedEffect = pplayer.getFixedEffectById(id);
if (fixedEffect == null) {
LangManager.sendMessage(p, Lang.FIXED_EDIT_INVALID_ID);
return;
}
String editType = args[1].toLowerCase();
if (editType.equals("location")) {
double xPos = -1, yPos = -1, zPos = -1;
if (args[2].equalsIgnoreCase("looking")) {
Block targetBlock = p.getTargetBlock((Set<Material>)null, 8);
int maxDistanceSqrd = 6 * 6;
if (targetBlock.getLocation().distanceSquared(p.getLocation()) > maxDistanceSqrd) {
LangManager.sendMessage(p, Lang.FIXED_EDIT_LOOKING_TOO_FAR);
return;
}
Location blockLocation = targetBlock.getLocation().clone().add(0.5, 0.5, 0.5); // Center of block
xPos = blockLocation.getX();
yPos = blockLocation.getY();
zPos = blockLocation.getZ();
} else {
try {
if (args[2].startsWith("~")) {
if (args[2].equals("~")) xPos = p.getLocation().getX();
else xPos = p.getLocation().getX() + Double.parseDouble(args[2].substring(1));
} else {
xPos = Double.parseDouble(args[2]);
}
if (args[3].startsWith("~")) {
if (args[3].equals("~")) yPos = p.getLocation().getY() + 1;
else yPos = p.getLocation().getY() + 1 + Double.parseDouble(args[3].substring(1));
} else {
yPos = Double.parseDouble(args[3]);
}
if (args[4].startsWith("~")) {
if (args[4].equals("~")) zPos = p.getLocation().getZ();
else zPos = p.getLocation().getZ() + Double.parseDouble(args[4].substring(1));
} else {
zPos = Double.parseDouble(args[4]);
}
} catch (Exception e) {
LangManager.sendMessage(p, Lang.FIXED_EDIT_INVALID_COORDS);
return;
}
}
double distanceFromEffect = p.getLocation().distance(new Location(p.getWorld(), xPos, yPos, zPos));
int maxCreationDistance = PermissionManager.getMaxFixedEffectCreationDistance();
if (maxCreationDistance != 0 && distanceFromEffect > maxCreationDistance) {
LangManager.sendMessage(p, Lang.FIXED_EDIT_OUT_OF_RANGE, maxCreationDistance);
return;
}
fixedEffect.setCoordinates(xPos, yPos, zPos);
} else if (editType.equals("effect")) {
ParticleEffect effect = ParticleEffect.fromName(args[2]);
if (effect == null) {
LangManager.sendMessage(pplayer, Lang.FIXED_EDIT_EFFECT_INVALID, args[2]);
return;
} else if (!PermissionManager.hasEffectPermission(pplayer.getPlayer(), effect)) {
LangManager.sendMessage(pplayer, Lang.FIXED_EDIT_EFFECT_NO_PERMISSION, effect.getName());
return;
}
fixedEffect.getParticlePair().setEffect(effect);
} else if (editType.equals("style")) {
ParticleStyle style = ParticleStyle.fromName(args[2]);
if (style == null) {
LangManager.sendMessage(pplayer, Lang.FIXED_EDIT_STYLE_INVALID, args[2]);
return;
} else if (!PermissionManager.hasStylePermission(pplayer.getPlayer(), style)) {
LangManager.sendMessage(pplayer, Lang.FIXED_EDIT_STYLE_NO_PERMISSION, style.getName());
return;
}
fixedEffect.getParticlePair().setStyle(style);
} else if (editType.equals("data")) {
Material itemData = null;
Material blockData = null;
OrdinaryColor colorData = null;
NoteColor noteColorData = null;
ParticleEffect effect = fixedEffect.getParticlePair().getEffect();
if (effect.hasProperty(ParticleProperty.COLORABLE)) {
if (effect == ParticleEffect.NOTE) {
if (args[2].equalsIgnoreCase("rainbow")) {
noteColorData = new NoteColor(99);
} else if (args[2].equalsIgnoreCase("random")) {
noteColorData = new NoteColor(98);
} else {
int note = -1;
try {
note = Integer.parseInt(args[2]);
} catch (Exception e) {
LangManager.sendMessage(p, Lang.FIXED_EDIT_DATA_ERROR);
return;
}
if (note < 0 || note > 24) {
LangManager.sendMessage(p, Lang.FIXED_EDIT_DATA_ERROR);
return;
}
noteColorData = new NoteColor(note);
}
} else {
if (args[2].equalsIgnoreCase("rainbow")) {
colorData = new OrdinaryColor(999, 999, 999);
} else if (args[2].equalsIgnoreCase("random")) {
colorData = new OrdinaryColor(998, 998, 998);
} else {
int r = -1;
int g = -1;
int b = -1;
try {
r = Integer.parseInt(args[2]);
g = Integer.parseInt(args[3]);
b = Integer.parseInt(args[4]);
} catch (Exception e) {
LangManager.sendMessage(p, Lang.FIXED_EDIT_DATA_ERROR);
return;
}
if (r < 0 || r > 255 || g < 0 || g > 255 || b < 0 || b > 255) {
LangManager.sendMessage(p, Lang.FIXED_EDIT_DATA_ERROR);
return;
}
colorData = new OrdinaryColor(r, g, b);
}
}
} else if (effect.hasProperty(ParticleProperty.REQUIRES_MATERIAL_DATA)) {
if (effect == ParticleEffect.BLOCK || effect == ParticleEffect.FALLING_DUST) {
Material material = null;
try {
material = ParticleUtils.closestMatch(args[2]);
if (material == null) material = Material.matchMaterial(args[2]);
if (material == null || !material.isBlock()) throw new Exception();
} catch (Exception e) {
LangManager.sendMessage(p, Lang.FIXED_EDIT_DATA_ERROR);
return;
}
blockData = material;
} else if (effect == ParticleEffect.ITEM) {
Material material = null;
try {
material = ParticleUtils.closestMatch(args[2]);
if (material == null) material = Material.matchMaterial(args[2]);
if (material == null || material.isBlock()) throw new Exception();
} catch (Exception e) {
LangManager.sendMessage(p, Lang.FIXED_EDIT_DATA_ERROR);
return;
}
itemData = material;
}
} else {
LangManager.sendMessage(pplayer, Lang.FIXED_EDIT_DATA_NONE);
return;
}
fixedEffect.getParticlePair().setColor(colorData);
fixedEffect.getParticlePair().setNoteColor(noteColorData);
fixedEffect.getParticlePair().setItemMaterial(itemData);
fixedEffect.getParticlePair().setBlockMaterial(blockData);
} else {
LangManager.sendMessage(p, Lang.FIXED_EDIT_INVALID_PROPERTY);
return;
}
DataManager.updateFixedEffect(fixedEffect);
LangManager.sendMessage(pplayer, Lang.FIXED_EDIT_SUCCESS, editType, id);
}
/**
* Handles the command /pp fixed remove
*
* @param pplayer The PPlayer
* @param p The Player
* @param args The command arguments
*/
private void handleRemove(PPlayer pplayer, Player p, String[] args) {
if (args.length < 1) {
LangManager.sendMessage(p, Lang.FIXED_REMOVE_NO_ARGS);
return;
}
int id = -1;
try {
id = Integer.parseInt(args[0]);
} catch (Exception e) {
LangManager.sendMessage(p, Lang.FIXED_REMOVE_ARGS_INVALID);
return;
}
if (pplayer.getFixedEffectById(id) != null) {
DataManager.removeFixedEffect(pplayer.getUniqueId(), id);
LangManager.sendMessage(p, Lang.FIXED_REMOVE_SUCCESS, id);
} else {
LangManager.sendMessage(p, Lang.FIXED_REMOVE_INVALID, id);
}
}
/**
* Handles the command /pp fixed list
*
* @param pplayer The PPlayer
* @param p The Player
* @param args The command arguments
*/
private void handleList(PPlayer pplayer, Player p, String[] args) {
List<Integer> ids = pplayer.getFixedEffectIds();
Collections.sort(ids);
if (ids.isEmpty()) {
LangManager.sendMessage(p, Lang.FIXED_LIST_NONE);
return;
}
String msg = "";
boolean first = true;
for (int id : ids) {
if (!first) msg += ", ";
else first = false;
msg += id;
}
LangManager.sendMessage(p, Lang.FIXED_LIST_SUCCESS, msg);
}
/**
* Handles the command /pp fixed info
*
* @param pplayer The PPlayer
* @param p The Player
* @param args The command arguments
*/
private void handleInfo(PPlayer pplayer, Player p, String[] args) {
if (args.length < 1) {
LangManager.sendMessage(p, Lang.FIXED_INFO_NO_ARGS);
return;
}
int id = -1;
try {
id = Integer.parseInt(args[0]);
} catch (Exception e) {
LangManager.sendMessage(p, Lang.FIXED_INFO_INVALID_ARGS);
return;
}
FixedParticleEffect fixedEffect = pplayer.getFixedEffectById(id);
if (fixedEffect == null) {
LangManager.sendMessage(p, Lang.FIXED_INFO_INVALID, id);
return;
}
ParticlePair particle = fixedEffect.getParticlePair();
DecimalFormat df = new DecimalFormat("0.##"); // Decimal formatter so the coords aren't super long
LangManager.sendMessage(p, // @formatter:off
Lang.FIXED_INFO_SUCCESS,
fixedEffect.getId(),
fixedEffect.getLocation().getWorld().getName(),
df.format(fixedEffect.getLocation().getX()),
df.format(fixedEffect.getLocation().getY()),
df.format(fixedEffect.getLocation().getZ()),
particle.getEffect().getName(),
particle.getStyle().getName(),
particle.getDataString()
); // @formatter:on
}
/**
* Handles the command /pp fixed clear
*
* @param pplayer The PPlayer
* @param p The Player
* @param args The command arguments
*/
private void handleClear(PPlayer pplayer, Player p, String[] args) {
if (!PermissionManager.canClearFixedEffects(p)) {
LangManager.sendMessage(p, Lang.FIXED_CLEAR_NO_PERMISSION);
return;
}
if (args.length < 1) {
LangManager.sendMessage(p, Lang.FIXED_CLEAR_NO_ARGS);
return;
}
int radius = -1;
try {
radius = Math.abs(Integer.parseInt(args[0]));
} catch (Exception e) {
LangManager.sendMessage(p, Lang.FIXED_CLEAR_INVALID_ARGS);
return;
}
ArrayList<FixedParticleEffect> fixedEffectsToRemove = new ArrayList<FixedParticleEffect>();
for (PPlayer ppl : ParticleManager.getPPlayers())
for (FixedParticleEffect fixedEffect : ppl.getFixedParticles())
if (fixedEffect.getLocation().getWorld().equals(p.getLocation().getWorld()) && fixedEffect.getLocation().distance(p.getLocation()) <= radius)
fixedEffectsToRemove.add(fixedEffect);
for (FixedParticleEffect fixedEffect : fixedEffectsToRemove)
DataManager.removeFixedEffect(fixedEffect.getOwnerUniqueId(), fixedEffect.getId());
LangManager.sendMessage(p, Lang.FIXED_CLEAR_SUCCESS, fixedEffectsToRemove.size(), radius);
}
public List<String> onTabComplete(PPlayer pplayer, String[] args) {
Player p = pplayer.getPlayer();
List<String> matches = new ArrayList<String>();
String[] subCommands = new String[] { "create", "edit", "remove", "list", "info", "clear" };
if (args.length <= 1) {
List<String> possibleCmds = new ArrayList<String>(Arrays.asList(subCommands));
if (args.length == 0) matches = possibleCmds;
else StringUtil.copyPartialMatches(args[0], possibleCmds, matches);
} else {
switch (args[0].toLowerCase()) {
case "create":
if (args.length >= 2 && args.length <= 4) {
List<String> possibleValues = new ArrayList<String>();
if (args.length == 4) {
possibleValues.add("~");
}
if (args.length == 3) {
possibleValues.add("~ ~");
}
if (args.length == 2) {
possibleValues.add("~ ~ ~");
possibleValues.add("looking");
}
StringUtil.copyPartialMatches(args[args.length - 1], possibleValues, matches);
}
// Pad arguments if the first coordinate is "looking"
if (args.length > 1 && args[1].equalsIgnoreCase("looking")) {
String[] paddedArgs = new String[args.length + 2];
paddedArgs[0] = paddedArgs[1] = paddedArgs[2] = paddedArgs[3] = "";
for (int i = 2; i < args.length; i++)
paddedArgs[i + 2] = args[i];
args = paddedArgs;
}
if (args.length == 5) {
StringUtil.copyPartialMatches(args[4], PermissionManager.getEffectNamesUserHasPermissionFor(p), matches);
} else if (args.length == 6) {
StringUtil.copyPartialMatches(args[5], PermissionManager.getStyleNamesUserHasPermissionFor(p), matches);
} else if (args.length >= 7) {
ParticleEffect effect = ParticleEffect.fromName(args[4]);
if (effect != null) {
if (effect.hasProperty(ParticleProperty.COLORABLE)) {
List<String> possibleValues = new ArrayList<String>();
if (effect == ParticleEffect.NOTE) { // Note data
if (args.length == 7) {
possibleValues.add("<0-24>");
possibleValues.add("rainbow");
possibleValues.add("random");
}
} else { // Color data
if (args.length <= 9 && !args[2].equalsIgnoreCase("rainbow") && !args[2].equalsIgnoreCase("random")) {
possibleValues.add("<0-255>");
}
if (args.length <= 8 && !args[2].equalsIgnoreCase("rainbow") && !args[2].equalsIgnoreCase("random")) {
possibleValues.add("<0-255> <0-255>");
}
if (args.length <= 7) {
possibleValues.add("<0-255> <0-255> <0-255>");
possibleValues.add("rainbow");
possibleValues.add("random");
}
}
StringUtil.copyPartialMatches(args[args.length - 1], possibleValues, matches);
} else if (args.length == 7 && effect.hasProperty(ParticleProperty.REQUIRES_MATERIAL_DATA)) {
if (effect == ParticleEffect.BLOCK || effect == ParticleEffect.FALLING_DUST) { // Block material
matches = StringUtil.copyPartialMatches(args[6], ParticleUtils.getAllBlockMaterials(), matches);
} else if (effect == ParticleEffect.ITEM) { // Item material
matches = StringUtil.copyPartialMatches(args[6], ParticleUtils.getAllItemMaterials(), matches);
}
}
}
}
break;
case "edit":
if (args.length == 2) {
StringUtil.copyPartialMatches(args[1], pplayer.getFixedEffectIds().stream().map((x) -> String.valueOf(x)).collect(Collectors.toList()), matches);
} else if (args.length == 3) {
String[] validProperties = new String[] { "location", "effect", "style", "data" };
StringUtil.copyPartialMatches(args[2], Arrays.asList(validProperties), matches);
} else if (args.length > 3) {
String property = args[2].toLowerCase();
if (property.equals("location")) {
List<String> possibleValues = new ArrayList<String>();
if (args.length == 6 && !args[3].equalsIgnoreCase("looking")) {
possibleValues.add("~");
}
if (args.length == 5 && !args[3].equalsIgnoreCase("looking")) {
possibleValues.add("~ ~");
}
if (args.length == 4) {
possibleValues.add("~ ~ ~");
possibleValues.add("looking");
}
StringUtil.copyPartialMatches(args[args.length - 1], possibleValues, matches);
} else if (property.equals("effect") && args.length == 4) {
StringUtil.copyPartialMatches(args[3], PermissionManager.getEffectNamesUserHasPermissionFor(p), matches);
} else if (property.equals("style") && args.length == 4) {
StringUtil.copyPartialMatches(args[3], PermissionManager.getStyleNamesUserHasPermissionFor(p), matches);
} else if (property.equals("data")) {
int id = -1;
try {
id = Integer.parseInt(args[1]);
} catch (Exception e) { }
FixedParticleEffect fixedEffect = pplayer.getFixedEffectById(id);
if (fixedEffect != null) {
ParticleEffect effect = fixedEffect.getParticlePair().getEffect();
if (effect.hasProperty(ParticleProperty.COLORABLE)) {
List<String> possibleValues = new ArrayList<String>();
if (effect == ParticleEffect.NOTE) { // Note data
if (args.length == 4) {
possibleValues.add("<0-24>");
possibleValues.add("rainbow");
possibleValues.add("random");
}
} else { // Color data
if (args.length == 6 && !args[3].equalsIgnoreCase("rainbow") && !args[3].equalsIgnoreCase("random")) {
possibleValues.add("<0-255>");
}
if (args.length == 5 && !args[3].equalsIgnoreCase("rainbow") && !args[3].equalsIgnoreCase("random")) {
possibleValues.add("<0-255> <0-255>");
}
if (args.length == 4) {
possibleValues.add("<0-255> <0-255> <0-255>");
possibleValues.add("rainbow");
possibleValues.add("random");
}
}
StringUtil.copyPartialMatches(args[args.length - 1], possibleValues, matches);
} else if (args.length == 4 && effect.hasProperty(ParticleProperty.REQUIRES_MATERIAL_DATA)) {
if (effect == ParticleEffect.BLOCK || effect == ParticleEffect.FALLING_DUST) { // Block material
matches = StringUtil.copyPartialMatches(args[3], ParticleUtils.getAllBlockMaterials(), matches);
} else if (effect == ParticleEffect.ITEM) { // Item material
matches = StringUtil.copyPartialMatches(args[3], ParticleUtils.getAllItemMaterials(), matches);
}
}
}
}
}
break;
case "remove":
StringUtil.copyPartialMatches(args[1], pplayer.getFixedEffectIds().stream().map((x) -> String.valueOf(x)).collect(Collectors.toList()), matches);
break;
case "list":
break;
case "info":
StringUtil.copyPartialMatches(args[1], pplayer.getFixedEffectIds().stream().map((x) -> String.valueOf(x)).collect(Collectors.toList()), matches);
break;
case "clear":
matches.add("<radius>");
break;
}
}
return matches;
}
public String getName() {
return "fixed";
}
public Lang getDescription() {
return Lang.COMMAND_DESCRIPTION_FIXED;
}
public String getArguments() {
return "<sub-command>";
}
public boolean requiresEffects() {
return true;
}
}

View file

@ -0,0 +1,61 @@
package com.esophose.playerparticles.command;
import java.util.ArrayList;
import java.util.List;
import com.esophose.playerparticles.gui.GuiHandler;
import com.esophose.playerparticles.manager.LangManager;
import com.esophose.playerparticles.manager.LangManager.Lang;
import com.esophose.playerparticles.manager.PermissionManager;
import com.esophose.playerparticles.particles.PPlayer;
public class GUICommandModule implements CommandModule {
public void onCommandExecute(PPlayer pplayer, String[] args) {
boolean byDefault = false;
if (args.length > 0 && args[0].equals("_byDefault_")) {
byDefault = true;
}
if (GuiHandler.isGuiDisabled()) {
if (byDefault) {
LangManager.sendMessage(pplayer, Lang.COMMAND_ERROR_UNKNOWN);
} else {
LangManager.sendMessage(pplayer, Lang.GUI_DISABLED);
}
return;
}
if (PermissionManager.getEffectNamesUserHasPermissionFor(pplayer.getPlayer()).isEmpty()) {
if (byDefault) {
LangManager.sendMessage(pplayer, Lang.COMMAND_ERROR_UNKNOWN);
} else {
LangManager.sendMessage(pplayer, Lang.COMMAND_ERROR_NO_EFFECTS);
}
return;
}
GuiHandler.openDefault(pplayer);
}
public List<String> onTabComplete(PPlayer pplayer, String[] args) {
return new ArrayList<String>();
}
public String getName() {
return "gui";
}
public Lang getDescription() {
return Lang.COMMAND_DESCRIPTION_GUI;
}
public String getArguments() {
return "";
}
public boolean requiresEffects() {
return true;
}
}

View file

@ -0,0 +1,306 @@
package com.esophose.playerparticles.command;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import org.bukkit.entity.Player;
import org.bukkit.util.StringUtil;
import com.esophose.playerparticles.manager.DataManager;
import com.esophose.playerparticles.manager.LangManager;
import com.esophose.playerparticles.manager.LangManager.Lang;
import com.esophose.playerparticles.manager.PermissionManager;
import com.esophose.playerparticles.particles.PPlayer;
import com.esophose.playerparticles.particles.ParticleGroup;
import com.esophose.playerparticles.particles.ParticlePair;
public class GroupCommandModule implements CommandModule {
public void onCommandExecute(PPlayer pplayer, String[] args) {
Player p = pplayer.getPlayer();
List<String> validCommands = Arrays.asList(new String[] { "save", "load", "remove", "info", "list" });
if (args.length == 0 || !validCommands.contains(args[0])) {
LangManager.sendMessage(p, Lang.COMMAND_DESCRIPTION_GROUP_SAVE);
LangManager.sendMessage(p, Lang.COMMAND_DESCRIPTION_GROUP_LOAD);
LangManager.sendMessage(p, Lang.COMMAND_DESCRIPTION_GROUP_REMOVE);
LangManager.sendMessage(p, Lang.COMMAND_DESCRIPTION_GROUP_INFO);
LangManager.sendMessage(p, Lang.COMMAND_DESCRIPTION_GROUP_LIST);
return;
}
if (args.length == 1 && !args[0].equalsIgnoreCase("list")) {
LangManager.sendMessage(p, Lang.GROUP_NO_NAME, args[0].toLowerCase());
return;
}
switch (args[0].toLowerCase()) {
case "save":
onSave(pplayer, args[1].toLowerCase());
break;
case "load":
onLoad(pplayer, args[1].toLowerCase());
break;
case "remove":
onRemove(pplayer, args[1].toLowerCase());
break;
case "info":
onInfo(pplayer, args[1].toLowerCase());
break;
case "list":
onList(pplayer);
break;
default:
LangManager.sendMessage(p, Lang.COMMAND_DESCRIPTION_GROUP_SAVE);
LangManager.sendMessage(p, Lang.COMMAND_DESCRIPTION_GROUP_LOAD);
LangManager.sendMessage(p, Lang.COMMAND_DESCRIPTION_GROUP_REMOVE);
LangManager.sendMessage(p, Lang.COMMAND_DESCRIPTION_GROUP_INFO);
LangManager.sendMessage(p, Lang.COMMAND_DESCRIPTION_GROUP_LIST);
break;
}
}
/**
* Handles the command /pp group save
*
* @param pplayer The PPlayer
* @param groupName The target group name
*/
private void onSave(PPlayer pplayer, String groupName) {
// Check that the groupName isn't the reserved name
if (groupName.equalsIgnoreCase(ParticleGroup.DEFAULT_NAME)) {
LangManager.sendMessage(pplayer, Lang.GROUP_RESERVED);
return;
}
// Check if the player actually has any particles
if (pplayer.getActiveParticles().size() == 0) {
LangManager.sendMessage(pplayer, Lang.GROUP_SAVE_NO_PARTICLES);
return;
}
// The database column can only hold up to 100 characters, cut it off there
if (groupName.length() >= 100) {
groupName = groupName.substring(0, 100);
}
// Check if they are creating a new group, if they are, check that they haven't gone over their limit
if (pplayer.getParticleGroupByName(groupName) == null && PermissionManager.hasPlayerReachedMaxGroups(pplayer)) {
LangManager.sendMessage(pplayer, Lang.GROUP_SAVE_REACHED_MAX);
return;
}
// Use the existing group if available, otherwise create a new one
ParticleGroup group = pplayer.getParticleGroupByName(groupName);
boolean groupUpdated = false;
if (group == null) {
List<ParticlePair> particles = new ArrayList<ParticlePair>();
for (ParticlePair particle : pplayer.getActiveParticles())
particles.add(particle.clone()); // Make sure the ParticlePairs aren't the same references in both the active and saved group
group = new ParticleGroup(groupName, particles);
} else {
groupUpdated = true;
}
// Apply changes and notify player
DataManager.saveParticleGroup(pplayer.getUniqueId(), group);
if (groupUpdated) {
LangManager.sendMessage(pplayer, Lang.GROUP_SAVE_SUCCESS_OVERWRITE, groupName);
} else {
LangManager.sendMessage(pplayer, Lang.GROUP_SAVE_SUCCESS, groupName);
}
}
/**
* Handles the command /pp group load
*
* @param pplayer The PPlayer
* @param groupName The target group name
*/
private void onLoad(PPlayer pplayer, String groupName) {
// Check that the groupName isn't the reserved name
if (groupName.equalsIgnoreCase(ParticleGroup.DEFAULT_NAME)) {
LangManager.sendMessage(pplayer, Lang.GROUP_RESERVED);
return;
}
// Get the group
boolean isPreset = false;
ParticleGroup group = pplayer.getParticleGroupByName(groupName);
if (group == null) {
// Didn't find a saved group, look at the presets
group = ParticleGroup.getPresetGroup(groupName);
if (group == null) {
LangManager.sendMessage(pplayer, Lang.GROUP_INVALID, groupName);
return;
}
if (!group.canPlayerUse(pplayer.getPlayer())) {
LangManager.sendMessage(pplayer, Lang.GROUP_PRESET_NO_PERMISSION, groupName);
return;
}
isPreset = true;
}
// Empty out the active group and fill it with clones from the target group
ParticleGroup activeGroup = pplayer.getActiveParticleGroup();
activeGroup.getParticles().clear();
for (ParticlePair particle : group.getParticles())
activeGroup.getParticles().add(particle.clone());
// Update group and notify player
DataManager.saveParticleGroup(pplayer.getUniqueId(), activeGroup);
if (!isPreset)
LangManager.sendMessage(pplayer, Lang.GROUP_LOAD_SUCCESS, activeGroup.getParticles().size(), groupName);
else
LangManager.sendMessage(pplayer, Lang.GROUP_LOAD_PRESET_SUCCESS, activeGroup.getParticles().size(), groupName);
}
/**
* Handles the command /pp group remove
*
* @param pplayer The PPlayer
* @param groupName The target group name
*/
private void onRemove(PPlayer pplayer, String groupName) {
// Check that the groupName isn't the reserved name
if (groupName.equalsIgnoreCase(ParticleGroup.DEFAULT_NAME)) {
LangManager.sendMessage(pplayer, Lang.GROUP_RESERVED);
return;
}
ParticleGroup group = pplayer.getParticleGroupByName(groupName);
if (group == null) {
// Didn't find a saved group, look at the presets
group = ParticleGroup.getPresetGroup(groupName);
if (group != null) {
LangManager.sendMessage(pplayer, Lang.GROUP_REMOVE_PRESET);
return;
}
}
// Delete the group and notify player
DataManager.removeParticleGroup(pplayer.getUniqueId(), group);
LangManager.sendMessage(pplayer, Lang.GROUP_REMOVE_SUCCESS, groupName);
}
/**
* Handles the command /pp group info
*
* @param pplayer The PPlayer
* @param groupName The target group name
*/
private void onInfo(PPlayer pplayer, String groupName) {
// Check that the groupName isn't the reserved name
if (groupName.equalsIgnoreCase(ParticleGroup.DEFAULT_NAME)) {
LangManager.sendMessage(pplayer, Lang.GROUP_RESERVED);
return;
}
ParticleGroup group = pplayer.getParticleGroupByName(groupName);
if (group == null) {
// Didn't find a saved group, look at the presets
group = ParticleGroup.getPresetGroup(groupName);
if (group == null) {
LangManager.sendMessage(pplayer, Lang.GROUP_INVALID, groupName);
return;
}
if (!group.canPlayerUse(pplayer.getPlayer())) {
LangManager.sendMessage(pplayer, Lang.GROUP_PRESET_NO_PERMISSION, groupName);
return;
}
}
List<ParticlePair> particles = group.getParticles();
particles.sort(Comparator.comparingInt(ParticlePair::getId));
LangManager.sendMessage(pplayer, Lang.GROUP_INFO_HEADER, groupName);
for (ParticlePair particle : particles)
LangManager.sendMessage(pplayer, Lang.LIST_OUTPUT, particle.getId(), particle.getEffect().getName(), particle.getStyle().getName(), particle.getDataString());
}
/**
* Handles the command /pp group list
*
* @param pplayer The PPlayer
*/
private void onList(PPlayer pplayer) {
List<ParticleGroup> groups = pplayer.getParticleGroups();
groups.sort(Comparator.comparing(ParticleGroup::getName));
String groupsList = "";
for (ParticleGroup group : groups)
if (!group.getName().equals(ParticleGroup.DEFAULT_NAME))
groupsList += group.getName() + ", ";
if (groupsList.endsWith(", "))
groupsList = groupsList.substring(0, groupsList.length() - 2);
String presetsList = "";
for (ParticleGroup group : ParticleGroup.getPresetGroupsForPlayer(pplayer.getPlayer()))
presetsList += group.getName() + ", ";
if (presetsList.endsWith(", "))
presetsList = presetsList.substring(0, presetsList.length() - 2);
if (groupsList.isEmpty() && presetsList.isEmpty()) {
LangManager.sendMessage(pplayer, Lang.GROUP_LIST_NONE);
return;
}
if (!groupsList.isEmpty()) {
LangManager.sendMessage(pplayer, Lang.GROUP_LIST_OUTPUT, groupsList);
}
if (!presetsList.isEmpty()) {
LangManager.sendMessage(pplayer, Lang.GROUP_LIST_PRESETS, presetsList);
}
}
public List<String> onTabComplete(PPlayer pplayer, String[] args) {
List<String> matches = new ArrayList<String>();
List<String> subCommands = Arrays.asList(new String[] { "save", "load", "remove", "info", "list" });
if (args.length <= 1) {
if (args.length == 0) matches = subCommands;
else StringUtil.copyPartialMatches(args[0], subCommands, matches);
} else if (args.length == 2 && !args[0].equalsIgnoreCase("list")) {
if (args[0].equalsIgnoreCase("save")) {
matches.add("<groupName>");
} else {
List<String> groupNames = new ArrayList<String>();
for (ParticleGroup group : pplayer.getParticleGroups())
if (!group.getName().equals(ParticleGroup.DEFAULT_NAME))
groupNames.add(group.getName());
if (!args[0].equals("remove"))
for (ParticleGroup group : ParticleGroup.getPresetGroupsForPlayer(pplayer.getPlayer()))
groupNames.add(group.getName());
StringUtil.copyPartialMatches(args[1], groupNames, matches);
}
}
return matches;
}
public String getName() {
return "group";
}
public Lang getDescription() {
return Lang.COMMAND_DESCRIPTION_GROUP;
}
public String getArguments() {
return "<sub-command>";
}
public boolean requiresEffects() {
return true;
}
}

View file

@ -0,0 +1,39 @@
package com.esophose.playerparticles.command;
import java.util.ArrayList;
import java.util.List;
import com.esophose.playerparticles.manager.LangManager.Lang;
import com.esophose.playerparticles.particles.PPlayer;
public class HelpCommandModule implements CommandModule {
public void onCommandExecute(PPlayer pplayer, String[] args) {
// TODO: Add pages, there are a lot of commands
List<CommandModule> cmds = ParticleCommandHandler.getCommands();
for (CommandModule cmd : cmds) {
CommandModule.printUsageWithDescription(pplayer, cmd);
}
}
public List<String> onTabComplete(PPlayer pplayer, String[] args) {
return new ArrayList<String>();
}
public String getName() {
return "help";
}
public Lang getDescription() {
return Lang.COMMAND_DESCRIPTION_HELP;
}
public String getArguments() {
return "";
}
public boolean requiresEffects() {
return false;
}
}

View file

@ -0,0 +1,53 @@
package com.esophose.playerparticles.command;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import com.esophose.playerparticles.manager.LangManager;
import com.esophose.playerparticles.manager.LangManager.Lang;
import com.esophose.playerparticles.particles.PPlayer;
import com.esophose.playerparticles.particles.ParticlePair;
public class ListCommandModule implements CommandModule {
public void onCommandExecute(PPlayer pplayer, String[] args) {
List<ParticlePair> particles = pplayer.getActiveParticles();
particles.sort(Comparator.comparingInt(ParticlePair::getId));
if (particles.isEmpty()) {
LangManager.sendMessage(pplayer, Lang.LIST_NONE);
return;
}
LangManager.sendMessage(pplayer, Lang.LIST_YOU_HAVE);
for (ParticlePair particle : particles) {
int id = particle.getId();
String effect = particle.getEffect().getName();
String style = particle.getStyle().getName();
String data = particle.getDataString();
LangManager.sendMessage(pplayer, Lang.LIST_OUTPUT, id, effect, style, data);
}
}
public List<String> onTabComplete(PPlayer pplayer, String[] args) {
return new ArrayList<String>();
}
public String getName() {
return "list";
}
public Lang getDescription() {
return Lang.COMMAND_DESCRIPTION_LIST;
}
public String getArguments() {
return "";
}
public boolean requiresEffects() {
return true;
}
}

View file

@ -0,0 +1,147 @@
package com.esophose.playerparticles.command;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.command.TabCompleter;
import org.bukkit.entity.Player;
import com.esophose.playerparticles.manager.DataManager;
import com.esophose.playerparticles.manager.LangManager;
import com.esophose.playerparticles.manager.LangManager.Lang;
import com.esophose.playerparticles.manager.PermissionManager;
public class ParticleCommandHandler implements CommandExecutor, TabCompleter {
/**
* A list of all commands
*/
private static List<CommandModule> commands;
static {
commands = new ArrayList<CommandModule>();
commands.add(new AddCommandModule());
commands.add(new DataCommandModule());
commands.add(new DefaultCommandModule());
commands.add(new EditCommandModule());
commands.add(new EffectCommandModule());
commands.add(new EffectsCommandModule());
commands.add(new FixedCommandModule());
commands.add(new GroupCommandModule());
commands.add(new GUICommandModule());
commands.add(new HelpCommandModule());
commands.add(new ListCommandModule());
commands.add(new ReloadCommandModule());
commands.add(new RemoveCommandModule());
commands.add(new ResetCommandModule());
commands.add(new StyleCommandModule());
commands.add(new StylesCommandModule());
commands.add(new VersionCommandModule());
commands.add(new WorldsCommandModule());
}
/**
* Finds a matching CommandModule by its name
*
* @param commandName The command name
* @return The found CommandModule, otherwise null
*/
public static CommandModule findMatchingCommand(String commandName) {
for (CommandModule commandModule : commands)
if (commandModule.getName().equalsIgnoreCase(commandName))
return commandModule;
return null;
}
/**
* Get a list of all available commands
*
* @return A List of all CommandModules registered
*/
public static List<CommandModule> getCommands() {
return commands;
}
/**
* Get all available command names
*
* @return All available command names
*/
public static List<String> getCommandNames() {
List<String> commandNames = new ArrayList<String>();
for (CommandModule cmd : commands)
commandNames.add(cmd.getName());
return commandNames;
}
/**
* Called when a player executes a /pp command
* Checks what /pp command it is and calls the corresponding module
*
* @param sender Who executed the command
* @param cmd The command
* @param label The command label
* @param args The arguments following the command
* @return true
*/
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
if (!(sender instanceof Player)) {
sender.sendMessage("Error: PlayerParticles only supports players executing commands.");
return true;
}
Player p = (Player) sender;
DataManager.getPPlayer(p.getUniqueId(), (pplayer) -> {
String commandName = args.length > 0 ? args[0] : "";
CommandModule commandModule = findMatchingCommand(commandName);
if (commandModule != null) {
if (commandModule.requiresEffects() && PermissionManager.getEffectNamesUserHasPermissionFor(p).isEmpty()) {
LangManager.sendMessage(p, Lang.COMMAND_ERROR_NO_EFFECTS);
} else {
String[] cmdArgs = new String[0];
if (args.length > 1) cmdArgs = Arrays.copyOfRange(args, 1, args.length);
commandModule.onCommandExecute(pplayer, cmdArgs);
}
} else {
LangManager.sendMessage(p, Lang.COMMAND_ERROR_UNKNOWN);
}
});
return true;
}
/**
* Activated when a user pushes tab in chat prefixed with /pp
*
* @param sender The sender that hit tab, should always be a player
* @param cmd The command the player is executing
* @param alias The possible alias for the command
* @param args All arguments following the command
* @return A list of commands available to the sender
*/
public List<String> onTabComplete(CommandSender sender, Command cmd, String alias, String[] args) {
if (!(sender instanceof Player)) return new ArrayList<String>();
if (cmd.getName().equalsIgnoreCase("pp")) {
if (args.length <= 1) {
CommandModule commandModule = findMatchingCommand(""); // Get the default command module
return commandModule.onTabComplete(DataManager.getPPlayer(((Player) sender).getUniqueId()), args);
} else if (args.length >= 2) {
CommandModule commandModule = findMatchingCommand(args[0]);
String[] cmdArgs = Arrays.copyOfRange(args, 1, args.length);
if (commandModule != null) {
return commandModule.onTabComplete(DataManager.getPPlayer(((Player) sender).getUniqueId()), cmdArgs);
}
}
}
return new ArrayList<String>();
}
}

View file

@ -0,0 +1,43 @@
package com.esophose.playerparticles.command;
import java.util.ArrayList;
import java.util.List;
import com.esophose.playerparticles.PlayerParticles;
import com.esophose.playerparticles.manager.LangManager;
import com.esophose.playerparticles.manager.LangManager.Lang;
import com.esophose.playerparticles.manager.PermissionManager;
import com.esophose.playerparticles.particles.PPlayer;
public class ReloadCommandModule implements CommandModule {
public void onCommandExecute(PPlayer pplayer, String[] args) {
if (PermissionManager.canReloadPlugin(pplayer.getPlayer())) {
((PlayerParticles)PlayerParticles.getPlugin()).reload(false);
LangManager.sendMessage(pplayer, Lang.RELOAD_SUCCESS);
} else {
LangManager.sendMessage(pplayer, Lang.RELOAD_NO_PERMISSION);
}
}
public List<String> onTabComplete(PPlayer pplayer, String[] args) {
return new ArrayList<String>();
}
public String getName() {
return "reload";
}
public Lang getDescription() {
return Lang.COMMAND_DESCRIPTION_RELOAD;
}
public String getArguments() {
return "";
}
public boolean requiresEffects() {
return false;
}
}

View file

@ -0,0 +1,84 @@
package com.esophose.playerparticles.command;
import java.util.ArrayList;
import java.util.List;
import org.bukkit.util.StringUtil;
import com.esophose.playerparticles.manager.DataManager;
import com.esophose.playerparticles.manager.LangManager;
import com.esophose.playerparticles.manager.LangManager.Lang;
import com.esophose.playerparticles.particles.PPlayer;
import com.esophose.playerparticles.particles.ParticleGroup;
import com.esophose.playerparticles.particles.ParticlePair;
public class RemoveCommandModule implements CommandModule {
public void onCommandExecute(PPlayer pplayer, String[] args) {
if (args.length == 0) {
LangManager.sendMessage(pplayer, Lang.REMOVE_NO_ARGS);
return;
}
int id = -1;
try {
id = Integer.parseInt(args[0]);
} catch (Exception ex) {
LangManager.sendMessage(pplayer, Lang.ID_INVALID);
return;
}
if (id <= 0) {
LangManager.sendMessage(pplayer, Lang.ID_INVALID);
return;
}
boolean removed = false;
ParticleGroup activeGroup = pplayer.getActiveParticleGroup();
for (ParticlePair particle : activeGroup.getParticles()) {
if (particle.getId() == id) {
activeGroup.getParticles().remove(particle);
removed = true;
break;
}
}
if (!removed) {
LangManager.sendMessage(pplayer, Lang.ID_UNKNOWN, id);
return;
}
DataManager.saveParticleGroup(pplayer.getUniqueId(), activeGroup);
LangManager.sendMessage(pplayer, Lang.REMOVE_SUCCESS, id);
}
public List<String> onTabComplete(PPlayer pplayer, String[] args) {
List<String> matches = new ArrayList<String>();
List<String> ids = new ArrayList<String>();
for (ParticlePair particles : pplayer.getActiveParticles())
ids.add(String.valueOf(particles.getId()));
if (args.length == 0) return ids;
StringUtil.copyPartialMatches(args[0], ids, matches);
return matches;
}
public String getName() {
return "remove";
}
public Lang getDescription() {
return Lang.COMMAND_DESCRIPTION_REMOVE;
}
public String getArguments() {
return "<id>";
}
public boolean requiresEffects() {
return true;
}
}

View file

@ -0,0 +1,40 @@
package com.esophose.playerparticles.command;
import java.util.ArrayList;
import java.util.List;
import com.esophose.playerparticles.manager.DataManager;
import com.esophose.playerparticles.manager.LangManager;
import com.esophose.playerparticles.manager.LangManager.Lang;
import com.esophose.playerparticles.particles.PPlayer;
import com.esophose.playerparticles.particles.ParticleGroup;
public class ResetCommandModule implements CommandModule {
public void onCommandExecute(PPlayer pplayer, String[] args) {
int particleCount = pplayer.getActiveParticles().size();
DataManager.saveParticleGroup(pplayer.getUniqueId(), ParticleGroup.getDefaultGroup());
LangManager.sendMessage(pplayer, Lang.RESET_SUCCESS, particleCount);
}
public List<String> onTabComplete(PPlayer pplayer, String[] args) {
return new ArrayList<String>();
}
public String getName() {
return "reset";
}
public Lang getDescription() {
return Lang.COMMAND_DESCRIPTION_RESET;
}
public String getArguments() {
return "";
}
public boolean requiresEffects() {
return false;
}
}

View file

@ -0,0 +1,36 @@
package com.esophose.playerparticles.command;
import java.util.ArrayList;
import java.util.List;
import com.esophose.playerparticles.manager.LangManager;
import com.esophose.playerparticles.manager.LangManager.Lang;
import com.esophose.playerparticles.particles.PPlayer;
public class StyleCommandModule implements CommandModule {
public void onCommandExecute(PPlayer pplayer, String[] args) {
LangManager.sendMessage(pplayer, Lang.COMMAND_DESCRIPTION_STYLE);
}
public List<String> onTabComplete(PPlayer pplayer, String[] args) {
return new ArrayList<String>();
}
public String getName() {
return "style";
}
public Lang getDescription() {
return Lang.COMMAND_DESCRIPTION_STYLE;
}
public String getArguments() {
return "";
}
public boolean requiresEffects() {
return true;
}
}

View file

@ -0,0 +1,51 @@
package com.esophose.playerparticles.command;
import java.util.ArrayList;
import java.util.List;
import org.bukkit.entity.Player;
import com.esophose.playerparticles.manager.LangManager;
import com.esophose.playerparticles.manager.LangManager.Lang;
import com.esophose.playerparticles.manager.PermissionManager;
import com.esophose.playerparticles.particles.PPlayer;
public class StylesCommandModule implements CommandModule {
public void onCommandExecute(PPlayer pplayer, String[] args) {
Player p = pplayer.getPlayer();
List<String> styleNames = PermissionManager.getStyleNamesUserHasPermissionFor(p);
String toSend = "";
for (String name : styleNames) {
toSend += name + ", ";
}
if (toSend.endsWith(", ")) {
toSend = toSend.substring(0, toSend.length() - 2);
}
LangManager.sendMessage(p, Lang.STYLE_LIST, toSend);
}
public List<String> onTabComplete(PPlayer pplayer, String[] args) {
return new ArrayList<String>();
}
public String getName() {
return "styles";
}
public Lang getDescription() {
return Lang.COMMAND_DESCRIPTION_STYLES;
}
public String getArguments() {
return "";
}
public boolean requiresEffects() {
return false;
}
}

View file

@ -0,0 +1,40 @@
package com.esophose.playerparticles.command;
import java.util.ArrayList;
import java.util.List;
import org.bukkit.ChatColor;
import com.esophose.playerparticles.PlayerParticles;
import com.esophose.playerparticles.manager.LangManager;
import com.esophose.playerparticles.manager.LangManager.Lang;
import com.esophose.playerparticles.particles.PPlayer;
public class VersionCommandModule implements CommandModule {
public void onCommandExecute(PPlayer pplayer, String[] args) {
LangManager.sendCustomMessage(pplayer, ChatColor.YELLOW + "Running PlayerParticles " + ChatColor.AQUA + "v" + PlayerParticles.getPlugin().getDescription().getVersion());
LangManager.sendCustomMessage(pplayer, ChatColor.YELLOW + "Plugin created by: " + ChatColor.AQUA + "Esophose");
}
public List<String> onTabComplete(PPlayer pplayer, String[] args) {
return new ArrayList<String>();
}
public String getName() {
return "version";
}
public Lang getDescription() {
return Lang.COMMAND_DESCRIPTION_VERSION;
}
public String getArguments() {
return "";
}
public boolean requiresEffects() {
return false;
}
}

View file

@ -0,0 +1,48 @@
package com.esophose.playerparticles.command;
import java.util.ArrayList;
import java.util.List;
import com.esophose.playerparticles.manager.LangManager;
import com.esophose.playerparticles.manager.LangManager.Lang;
import com.esophose.playerparticles.manager.PermissionManager;
import com.esophose.playerparticles.particles.PPlayer;
public class WorldsCommandModule implements CommandModule {
public void onCommandExecute(PPlayer pplayer, String[] args) {
if (PermissionManager.getDisabledWorlds() == null || PermissionManager.getDisabledWorlds().isEmpty()) {
LangManager.sendMessage(pplayer, Lang.DISABLED_WORLDS_NONE);
return;
}
String worlds = "";
for (String s : PermissionManager.getDisabledWorlds()) {
worlds += s + ", ";
}
if (worlds.length() > 2) worlds = worlds.substring(0, worlds.length() - 2);
LangManager.sendCustomMessage(pplayer, LangManager.getText(Lang.DISABLED_WORLDS) + " " + worlds);
}
public List<String> onTabComplete(PPlayer pplayer, String[] args) {
return new ArrayList<String>();
}
public String getName() {
return "worlds";
}
public Lang getDescription() {
return Lang.COMMAND_DESCRIPTION_WORLDS;
}
public String getArguments() {
return "";
}
public boolean requiresEffects() {
return false;
}
}

View file

@ -0,0 +1,34 @@
package com.esophose.playerparticles.database;
import java.sql.Connection;
import java.sql.SQLException;
public interface DatabaseConnector {
/**
* Checks if the connection to the database has been created
*
* @return If the connection is created or not
*/
public boolean isInitialized();
/**
* Closes all open connections to the database
*/
public void closeConnection();
/**
* Executes a callback with a Connection passed and automatically closes it when finished
*
* @param callback The callback to execute once the connection is retrieved
*/
public void connect(ConnectionCallback callback);
/**
* Allows Lambda expressions to be used to reduce duplicated code for getting connections
*/
public static interface ConnectionCallback {
public void execute(Connection connection) throws SQLException;
}
}

View file

@ -0,0 +1,53 @@
package com.esophose.playerparticles.database;
import java.sql.Connection;
import java.sql.SQLException;
import com.esophose.playerparticles.PlayerParticles;
import com.esophose.playerparticles.manager.SettingManager.PSetting;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
public class MySqlDatabaseConnector implements DatabaseConnector {
private HikariDataSource hikari;
private boolean initializedSuccessfully = false;
public MySqlDatabaseConnector() {
String hostname = PSetting.DATABASE_HOSTNAME.getString();
String port = PSetting.DATABASE_PORT.getString();
String database = PSetting.DATABASE_NAME.getString();
String user = PSetting.DATABASE_USER_NAME.getString();
String pass = PSetting.DATABASE_USER_PASSWORD.getString();
HikariConfig config = new HikariConfig();
config.setJdbcUrl("jdbc:mysql://" + hostname + ":" + port + "/" + database);
config.setUsername(user);
config.setPassword(pass);
config.setMaximumPoolSize(5);
try {
hikari = new HikariDataSource(config);
initializedSuccessfully = true;
} catch (Exception ex) {
initializedSuccessfully = false;
}
}
public boolean isInitialized() {
return initializedSuccessfully;
}
public void closeConnection() {
hikari.close();
}
public void connect(ConnectionCallback callback) {
try (Connection connection = hikari.getConnection()) {
callback.execute(connection);
} catch (SQLException ex) {
PlayerParticles.getPlugin().getLogger().severe("An error occurred retrieving a mysql database connection: " + ex.getMessage());
}
}
}

View file

@ -0,0 +1,34 @@
package com.esophose.playerparticles.database;
import java.io.File;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import com.esophose.playerparticles.PlayerParticles;
public class SqliteDatabaseConnector implements DatabaseConnector {
private final String connectionString;
public SqliteDatabaseConnector(String directory) {
this.connectionString = "jdbc:sqlite:" + directory + File.separator + "playerparticles.db";
}
public boolean isInitialized() {
return true; // Always available
}
public void closeConnection() {
// Nothing to do
}
public void connect(ConnectionCallback callback) {
try (Connection connection = DriverManager.getConnection(this.connectionString)) {
callback.execute(connection);
} catch (SQLException ex) {
PlayerParticles.getPlugin().getLogger().severe("An error occurred retrieving an sqlite database connection: " + ex.getMessage());
}
}
}

View file

@ -1,56 +0,0 @@
package com.esophose.playerparticles.gui;
import org.bukkit.DyeColor;
import org.bukkit.Material;
import com.esophose.playerparticles.particles.ParticleEffect.OrdinaryColor;
public class ColorData {
private DyeColor dyeColor;
private Material material;
private OrdinaryColor ordinaryColor;
private String name;
public ColorData(DyeColor dyeColor, Material material, OrdinaryColor ordinaryColor, String name) {
this.dyeColor = dyeColor;
this.material = material;
this.ordinaryColor = ordinaryColor;
this.name = name;
}
/**
* Get the DyeColor
*
* @return The DyeColor
*/
public DyeColor getDyeColor() {
return this.dyeColor;
}
/**
* Get the Material representing this color
*
* @return The Material
*/
public Material getMaterial() {
return this.material;
}
/**
* Get the OrdinaryColor representing this color
*
* @return The OrdinaryColor
*/
public OrdinaryColor getOrdinaryColor() {
return this.ordinaryColor;
}
/**
* Get the name of this color
*
* @return The name of this color
*/
public String getName() {
return this.name;
}
}

View file

@ -0,0 +1,158 @@
package com.esophose.playerparticles.gui;
import java.util.Arrays;
import org.bukkit.Material;
import org.bukkit.inventory.ItemFlag;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.material.Dye;
import com.esophose.playerparticles.gui.GuiInventoryEditData.ColorData;
public class GuiActionButton {
private int slot;
private Material[] icons;
private ColorData[] colors;
private String name;
private String[] lore;
private GuiActionButtonClickCallback onClick;
private int iconIndex;
/**
* Constructor for creating animated icons
*
* @param slot The slot ID of the inventory
* @param icons The Materials that this icon will cycle through
* @param name The name that this icon will use
* @param lore The lore of this icon
* @param onClick The callback to execute when this button is clicked
*/
public GuiActionButton(int slot, Material[] icons, String name, String[] lore, GuiActionButtonClickCallback onClick) {
this.slot = slot;
this.icons = icons;
this.colors = null;
this.name = name;
this.lore = lore;
this.onClick = onClick;
}
/**
* Constructor for creating non-animated icons
*
* @param slot The slot ID of the inventory
* @param icon The Material that this icon will use
* @param name The name that this icon will use
* @param lore The lore of this icon
* @param onClick The callback to execute when this button is clicked
*/
public GuiActionButton(int slot, Material icon, String name, String[] lore, GuiActionButtonClickCallback onClick) {
this(slot, new Material[] { icon }, name, lore, onClick);
}
/**
* Constructor for creating animated icons using dyes
*
* @param slot The slot ID of the inventory
* @param iconColors The ColorData that this icon will cycle through
* @param name The name that this icon will use
* @param lore The lore of this icon
* @param onClick The callback to execute when this button is clicked
*/
public GuiActionButton(int slot, ColorData[] iconColors, String name, String[] lore, GuiActionButtonClickCallback onClick) {
this.slot = slot;
this.icons = null;
this.colors = iconColors;
this.name = name;
this.lore = lore;
this.onClick = onClick;
}
/**
* Constructor for creating non-animated icons using dyes
*
* @param slot The slot ID of the inventory
* @param iconColor The ColorData that this icon will use
* @param name The name that this icon will use
* @param lore The lore of this icon
* @param onClick The callback to execute when this button is clicked
*/
public GuiActionButton(int slot, ColorData iconColor, String name, String[] lore, GuiActionButtonClickCallback onClick) {
this(slot, new ColorData[] { iconColor }, name, lore, onClick);
}
/**
* Gets the slot this GuiActionButton occupies in the GuiInventory
*
* @return The slot this GuiActionButton occupies in the GuiInventory
*/
public int getSlot() {
return this.slot;
}
/**
* Gets the ItemStack icon that goes into the GUI
*
* @return The icon ItemStack for the GUI
*/
@SuppressWarnings("deprecation")
public ItemStack getIcon() {
ItemStack itemStack;
if (this.icons != null) {
itemStack = new ItemStack(this.icons[this.iconIndex]);
} else {
if (this.colors[0].getMaterial() != null) { // Use Materials
itemStack = new ItemStack(this.colors[this.iconIndex].getMaterial());
} else { // Use Dyes
itemStack = new Dye(this.colors[this.iconIndex].getDyeColor()).toItemStack(1);
}
}
ItemMeta itemMeta = itemStack.getItemMeta();
itemMeta.setDisplayName(this.name);
itemMeta.setLore(Arrays.asList(this.lore));
itemMeta.addItemFlags(ItemFlag.HIDE_ATTRIBUTES, ItemFlag.HIDE_POTION_EFFECTS);
itemStack.setItemMeta(itemMeta);
return itemStack;
}
/**
* Executes the onClick callback passed in the constructor
*
* @param button The button that was clicked
* @param isShiftClick If the player was holding shift when they clicked
*/
public void handleClick(GuiActionButton button, boolean isShiftClick) {
if (this.onClick != null)
this.onClick.execute(this, isShiftClick);
}
/**
* Ticked at an interval to allow the icon/name to update
*/
public void onTick() {
this.iconIndex = (this.iconIndex + 1) % (this.icons != null ? this.icons.length : this.colors.length);
}
/**
* Checks if this GuiActionButton has more than one icon/name that it can cycle through
*
* @return If this GuiActionButton has more than one icon/name
*/
public boolean isTickable() {
return this.icons != null ? this.icons.length > 1 : this.colors.length > 1;
}
/**
* Allows button click callbacks as parameters
*/
@FunctionalInterface
public static interface GuiActionButtonClickCallback {
public void execute(GuiActionButton button, boolean isShiftClick);
}
}

View file

@ -0,0 +1,159 @@
package com.esophose.playerparticles.gui;
import java.util.ArrayList;
import java.util.List;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.scheduler.BukkitRunnable;
import org.bukkit.scheduler.BukkitTask;
import com.esophose.playerparticles.PlayerParticles;
import com.esophose.playerparticles.manager.DataManager;
import com.esophose.playerparticles.manager.SettingManager.PSetting;
import com.esophose.playerparticles.particles.PPlayer;
/**
* This class provides a collection of static methods for modifying your
* particle/style/data through the use of a GUI
*/
public class GuiHandler extends BukkitRunnable implements Listener {
private static List<GuiInventory> guiInventories = new ArrayList<GuiInventory>();
private static BukkitTask guiTask = null;
/**
* Initializes all the static values for this class
*/
public static void setup() {
if (guiTask != null)
guiTask.cancel();
guiTask = new GuiHandler().runTaskTimer(PlayerParticles.getPlugin(), 0, 10);
}
/**
* Ticks GuiInventories
* Removes entries from playerGuiInventories if the player no longer has the inventory open or is offline
*/
public void run() {
List<GuiInventory> toRemoveList = new ArrayList<GuiInventory>();
for (GuiInventory inventory : guiInventories) {
PPlayer pplayer = DataManager.getPPlayer(inventory.getPPlayer().getUniqueId());
if (pplayer == null) {
toRemoveList.add(inventory);
continue;
}
Player player = Bukkit.getPlayer(inventory.getPPlayer().getUniqueId());
if (player == null) {
toRemoveList.add(inventory);
continue;
}
if (!inventory.getInventory().equals(player.getOpenInventory().getTopInventory())) {
toRemoveList.add(inventory);
continue;
}
inventory.onTick();
}
for (GuiInventory inventory : toRemoveList)
guiInventories.remove(inventory);
}
@EventHandler(priority = EventPriority.HIGHEST)
public void onInventoryClick(InventoryClickEvent event) {
if (!(event.getWhoClicked() instanceof Player)) return;
Player player = (Player)event.getWhoClicked();
GuiInventory inventory = getGuiInventory(player);
if (inventory == null) return;
event.setCancelled(true);
inventory.onClick(event);
}
/**
* Gets if the GUI is disabled by the server owner or not
*
* @return True if the GUI is disabled
*/
public static boolean isGuiDisabled() {
return !PSetting.GUI_ENABLED.getBoolean();
}
/**
* Forcefully closes all open PlayerParticles GUIs
* Used for when the plugin unloads so players can't take items from the GUI
*/
public static void forceCloseAllOpenGUIs() {
for (Player player : Bukkit.getOnlinePlayers()) {
for (GuiInventory inventory : guiInventories) {
if (inventory.getPPlayer().getUniqueId().equals(player.getUniqueId()) && inventory.getInventory().equals(player.getOpenInventory().getTopInventory())) {
player.closeInventory();
break;
}
}
}
guiInventories.clear();
}
/**
* Opens the default GUI screen for a player
*
* @param pplayer The PPlayer to open the GUI screen for
*/
public static void openDefault(PPlayer pplayer) {
removeGuiInventory(pplayer);
GuiInventoryDefault defaultInventory = new GuiInventoryDefault(pplayer);
guiInventories.add(defaultInventory);
pplayer.getPlayer().openInventory(defaultInventory.getInventory());
}
/**
* Changes the player's inventory to another one
*
* @param nextInventory The GuiInventory to transition to
*/
protected static void transition(GuiInventory nextInventory) {
removeGuiInventory(nextInventory.getPPlayer());
guiInventories.add(nextInventory);
nextInventory.getPPlayer().getPlayer().openInventory(nextInventory.getInventory());
}
/**
* Gets a GuiInventory by Player
*
* @param player The Player
* @return The GuiInventory belonging to the Player, if any
*/
private static GuiInventory getGuiInventory(Player player) {
for (GuiInventory inventory : guiInventories)
if (inventory.getPPlayer().getUniqueId().equals(player.getUniqueId()))
return inventory;
return null;
}
/**
* Removes a GuiInventory from guiInventories by a PPlayer
*
* @param pplayer The PPlayer who owns the GuiInventory
*/
private static void removeGuiInventory(PPlayer pplayer) {
for (GuiInventory inventory : guiInventories) {
if (inventory.getPPlayer().getUniqueId().equals(pplayer.getUniqueId())) {
guiInventories.remove(inventory);
break;
}
}
}
}

View file

@ -1,61 +1,150 @@
/**
* 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.List;
import org.bukkit.Material;
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 com.esophose.playerparticles.gui.PlayerParticlesGui.GuiState;
import com.esophose.playerparticles.particles.PPlayer;
import com.esophose.playerparticles.util.ParticleUtils;
public class GuiInventory {
private Inventory inventory;
private GuiState guiState;
public GuiInventory(Inventory inventory, GuiState guiState) {
public abstract class GuiInventory {
protected enum BorderColor {
WHITE(0, "WHITE_STAINED_GLASS_PANE"),
ORANGE(1, "ORANGE_STAINED_GLASS_PANE"),
RED(14, "RED_STAINED_GLASS_PANE"),
BROWN(12, "BROWN_STAINED_GLASS_PANE"),
GREEN(13, "GREEN_STAINED_GLASS_PANE");
private short data;
private Material material;
private BorderColor(int data, String materialName) {
this.data = (short)data;
this.material = ParticleUtils.closestMatch(materialName);
}
@SuppressWarnings("deprecation")
protected ItemStack getIcon() {
ItemStack borderIcon;
if (this.material != null) { // Use 1.13 materials
borderIcon = new ItemStack(this.material, 1);
} else { // Use < 1.13 data values
borderIcon = new ItemStack(ParticleUtils.closestMatch("THIN_GLASS"), 1, this.data);
}
ItemMeta meta = borderIcon.getItemMeta();
meta.setDisplayName(" ");
meta.addItemFlags(ItemFlag.HIDE_ATTRIBUTES, ItemFlag.HIDE_POTION_EFFECTS, ItemFlag.HIDE_ENCHANTS);
borderIcon.setItemMeta(meta);
return borderIcon;
}
}
protected static final int INVENTORY_SIZE = 54;
protected PPlayer pplayer;
protected Inventory inventory;
protected List<GuiActionButton> actionButtons;
public GuiInventory(PPlayer pplayer, Inventory inventory) {
this.pplayer = pplayer;
this.inventory = inventory;
this.guiState = guiState;
this.actionButtons = new ArrayList<GuiActionButton>();
}
/**
* Replaces the current inventory with a new inventory
* Gets the PPlayer this GuiInventory is managing
*
* @param inventory The inventory this GuiInventory now manages
* @return The PPlayer this GuiInventory is managing
*/
public void setInventory(Inventory inventory) {
this.inventory = inventory;
public PPlayer getPPlayer() {
return this.pplayer;
}
/**
* Updates the current GuiState
* Gets the Inventory this GuiInventory is managing
*
* @param guiState The new GuiState
*/
public void setGuiState(GuiState guiState) {
this.guiState = guiState;
}
/**
* Gets the Inventory
*
* @return The Inventory
* @return The Inventory this GuiInventory is managing
*/
public Inventory getInventory() {
return this.inventory;
}
/**
* Gets the GuiState
* Fills the border of the inventory with a given color
*
* @return The GuiState
* @param borderColor The color of the border
*/
public GuiState getGuiState() {
return this.guiState;
protected void fillBorder(BorderColor borderColor) {
ItemStack itemStack = borderColor.getIcon();
// Top
for (int i = 0; i < 9; i++)
this.inventory.setItem(i, itemStack);
// Bottom
for (int i = INVENTORY_SIZE - 9; i < INVENTORY_SIZE; i++)
this.inventory.setItem(i, itemStack);
// Left
for (int i = 0; i < INVENTORY_SIZE; i += 9)
this.inventory.setItem(i, itemStack);
// Right
for (int i = 8; i < INVENTORY_SIZE; i += 9)
this.inventory.setItem(i, itemStack);
}
/**
* Populates the Inventory with the contents of actionButtons
*/
protected void populate() {
for (GuiActionButton button : actionButtons) {
this.inventory.setItem(button.getSlot(), button.getIcon());
}
}
/**
* Ticked at an interval to animate GuiActionButton icons
*/
public void onTick() {
for (GuiActionButton button : this.actionButtons) {
if (button.isTickable()) {
button.onTick();
this.inventory.setItem(button.getSlot(), button.getIcon());
}
}
}
/**
* Handles clicks of GuiActionButtons
*
* @param event The InventoryClickEvent triggered when the player clicks in a GuiInventory
*/
public void onClick(InventoryClickEvent event) {
if (event.getClickedInventory() == null || !event.getClickedInventory().equals(this.inventory)) return;
int slot = event.getSlot();
boolean isShiftClick = event.isShiftClick();
for (GuiActionButton button : this.actionButtons) {
if (button.getSlot() == slot) {
button.handleClick(button, isShiftClick);
break;
}
}
}
@FunctionalInterface
public static interface GuiInventoryEditFinishedCallback {
public void execute();
}
}

View file

@ -0,0 +1,82 @@
package com.esophose.playerparticles.gui;
import java.util.Arrays;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.SkullType;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.SkullMeta;
import com.esophose.playerparticles.manager.LangManager;
import com.esophose.playerparticles.manager.LangManager.Lang;
import com.esophose.playerparticles.manager.SettingManager.GuiIcon;
import com.esophose.playerparticles.particles.PPlayer;
import com.esophose.playerparticles.util.ParticleUtils;
@SuppressWarnings("deprecation")
public class GuiInventoryDefault extends GuiInventory {
public GuiInventoryDefault(PPlayer pplayer) {
super(pplayer, Bukkit.createInventory(pplayer.getPlayer(), INVENTORY_SIZE, LangManager.getText(Lang.GUI_PLAYERPARTICLES)));
this.fillBorder(BorderColor.WHITE);
// PPlayer information icon
ItemStack headIcon;
Material playerHead = ParticleUtils.closestMatch("PLAYER_HEAD");
if (playerHead != null) {
headIcon = new ItemStack(playerHead, 1);
} else {
headIcon = new ItemStack(ParticleUtils.closestMatch("SKULL_ITEM"), 1, (short) SkullType.PLAYER.ordinal());
}
SkullMeta currentIconMeta = (SkullMeta) headIcon.getItemMeta();
currentIconMeta.setDisplayName(LangManager.getText(Lang.GUI_COLOR_ICON_NAME) + pplayer.getPlayer().getName());
String[] currentIconLore = new String[] {
LangManager.getText(Lang.GUI_COLOR_INFO) + LangManager.getText(Lang.GUI_ACTIVE_PARTICLES, pplayer.getActiveParticles().size()),
LangManager.getText(Lang.GUI_COLOR_INFO) + LangManager.getText(Lang.GUI_SAVED_GROUPS, pplayer.getParticleGroups().size()),
LangManager.getText(Lang.GUI_COLOR_INFO) + LangManager.getText(Lang.GUI_FIXED_EFFECTS, pplayer.getFixedEffectIds().size()),
"",
LangManager.getText(Lang.GUI_COLOR_INFO) + LangManager.getText(Lang.GUI_COMMANDS_INFO)
};
currentIconMeta.setLore(Arrays.asList(currentIconLore));
currentIconMeta.setOwner(pplayer.getPlayer().getName());
headIcon.setItemMeta(currentIconMeta);
this.inventory.setItem(13, headIcon);
// Manage Your Particles button
GuiActionButton manageYourParticlesButton = new GuiActionButton(38,
GuiIcon.PARTICLES.get(),
LangManager.getText(Lang.GUI_COLOR_ICON_NAME) + LangManager.getText(Lang.GUI_MANAGE_YOUR_PARTICLES),
new String[] { LangManager.getText(Lang.GUI_COLOR_INFO) + LangManager.getText(Lang.GUI_MANAGE_YOUR_PARTICLES_DESCRIPTION) },
(button, isShiftClick) -> {
GuiHandler.transition(new GuiInventoryManageParticles(pplayer));
});
this.actionButtons.add(manageYourParticlesButton);
// Manage Your Groups button
GuiActionButton manageYourGroupsButton = new GuiActionButton(40,
GuiIcon.GROUPS.get(),
LangManager.getText(Lang.GUI_COLOR_ICON_NAME) + LangManager.getText(Lang.GUI_MANAGE_YOUR_GROUPS),
new String[] { LangManager.getText(Lang.GUI_COLOR_INFO) + LangManager.getText(Lang.GUI_MANAGE_YOUR_GROUPS_DESCRIPTION) },
(button, isShiftClick) -> {
GuiHandler.transition(new GuiInventoryManageGroups(pplayer));
});
this.actionButtons.add(manageYourGroupsButton);
// Load Preset Groups
GuiActionButton loadPresetGroups = new GuiActionButton(42,
GuiIcon.PRESET_GROUPS.get(),
LangManager.getText(Lang.GUI_COLOR_ICON_NAME) + LangManager.getText(Lang.GUI_LOAD_A_PRESET_GROUP),
new String[] { LangManager.getText(Lang.GUI_COLOR_INFO) + LangManager.getText(Lang.GUI_LOAD_A_PRESET_GROUP_DESCRIPTION) },
(button, isShiftClick) -> {
GuiHandler.transition(new GuiInventoryLoadPresetGroups(pplayer));
});
this.actionButtons.add(loadPresetGroups);
this.populate();
}
}

View file

@ -0,0 +1,384 @@
package com.esophose.playerparticles.gui;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.DyeColor;
import org.bukkit.Material;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import com.esophose.playerparticles.manager.LangManager;
import com.esophose.playerparticles.manager.LangManager.Lang;
import com.esophose.playerparticles.manager.SettingManager.GuiIcon;
import com.esophose.playerparticles.particles.PPlayer;
import com.esophose.playerparticles.particles.ParticleEffect;
import com.esophose.playerparticles.particles.ParticleEffect.NoteColor;
import com.esophose.playerparticles.particles.ParticleEffect.OrdinaryColor;
import com.esophose.playerparticles.particles.ParticleEffect.ParticleProperty;
import com.esophose.playerparticles.particles.ParticlePair;
import com.esophose.playerparticles.util.ParticleUtils;
@SuppressWarnings("deprecation")
public class GuiInventoryEditData extends GuiInventory {
private static Random RANDOM = new Random();
private static List<Material> BLOCK_MATERIALS, ITEM_MATERIALS;
private static ColorData[] colorMapping;
private static ColorData[] rainbowColorMapping;
private static ColorData[] noteColorMapping;
static {
colorMapping = new ColorData[] {
new ColorData(DyeColor.RED, ParticleUtils.closestMatch("ROSE_RED"), new OrdinaryColor(255, 0, 0), Lang.GUI_EDIT_DATA_COLOR_RED),
new ColorData(DyeColor.ORANGE, ParticleUtils.closestMatch("ORANGE_DYE"), new OrdinaryColor(255, 140, 0), Lang.GUI_EDIT_DATA_COLOR_ORANGE),
new ColorData(DyeColor.YELLOW, ParticleUtils.closestMatch("DANDELION_YELLOW"), new OrdinaryColor(255, 255, 0), Lang.GUI_EDIT_DATA_COLOR_YELLOW),
new ColorData(DyeColor.LIME, ParticleUtils.closestMatch("LIME_DYE"), new OrdinaryColor(50, 205, 50), Lang.GUI_EDIT_DATA_COLOR_LIME_GREEN),
new ColorData(DyeColor.GREEN, ParticleUtils.closestMatch("CACTUS_GREEN"), new OrdinaryColor(0, 128, 0), Lang.GUI_EDIT_DATA_COLOR_GREEN),
new ColorData(DyeColor.BLUE, ParticleUtils.closestMatch("LAPIS_LAZULI"), new OrdinaryColor(0, 0, 255), Lang.GUI_EDIT_DATA_COLOR_BLUE),
new ColorData(DyeColor.CYAN, ParticleUtils.closestMatch("CYAN_DYE"), new OrdinaryColor(0, 139, 139), Lang.GUI_EDIT_DATA_COLOR_CYAN),
new ColorData(DyeColor.LIGHT_BLUE, ParticleUtils.closestMatch("LIGHT_BLUE_DYE"), new OrdinaryColor(173, 216, 230), Lang.GUI_EDIT_DATA_COLOR_LIGHT_BLUE),
new ColorData(DyeColor.PURPLE, ParticleUtils.closestMatch("PURPLE_DYE"), new OrdinaryColor(138, 43, 226), Lang.GUI_EDIT_DATA_COLOR_PURPLE),
new ColorData(DyeColor.MAGENTA, ParticleUtils.closestMatch("MAGENTA_DYE"), new OrdinaryColor(202, 31, 123), Lang.GUI_EDIT_DATA_COLOR_MAGENTA),
new ColorData(DyeColor.PINK, ParticleUtils.closestMatch("PINK_DYE"), new OrdinaryColor(255, 182, 193), Lang.GUI_EDIT_DATA_COLOR_PINK),
new ColorData(DyeColor.BROWN, ParticleUtils.closestMatch("COCOA_BEANS"), new OrdinaryColor(139, 69, 19), Lang.GUI_EDIT_DATA_COLOR_BROWN),
new ColorData(DyeColor.BLACK, ParticleUtils.closestMatch("INK_SAC"), new OrdinaryColor(0, 0, 0), Lang.GUI_EDIT_DATA_COLOR_BLACK),
new ColorData(DyeColor.GRAY, ParticleUtils.closestMatch("GRAY_DYE"), new OrdinaryColor(128, 128, 128), Lang.GUI_EDIT_DATA_COLOR_GRAY),
new ColorData(DyeColor.getByDyeData((byte)7), ParticleUtils.closestMatch("LIGHT_GRAY_DYE"), new OrdinaryColor(192, 192, 192), Lang.GUI_EDIT_DATA_COLOR_LIGHT_GRAY),
new ColorData(DyeColor.WHITE, ParticleUtils.closestMatch("BONE_MEAL"), new OrdinaryColor(255, 255, 255), Lang.GUI_EDIT_DATA_COLOR_WHITE),
};
rainbowColorMapping = new ColorData[] {
colorMapping[0], // Red
colorMapping[1], // Orange
colorMapping[2], // Yellow
colorMapping[3], // Lime
colorMapping[7], // Light Blue
colorMapping[5], // Blue
colorMapping[8] // Purple
};
// Note: This is supposed to be a rainbow but there's actually a bug in Minecraft since 1.8 that makes a bunch of them gray
noteColorMapping = new ColorData[] {
colorMapping[7], // Light Blue
colorMapping[7], // Light Blue
colorMapping[13], // Gray
colorMapping[10], // Pink
colorMapping[9], // Magenta
colorMapping[9], // Magenta
colorMapping[0], // Red
colorMapping[2], // Yellow
colorMapping[2], // Yellow
colorMapping[14], // Light Gray
colorMapping[13], // Gray
colorMapping[6], // Cyan
colorMapping[6], // Cyan
colorMapping[6], // Cyan
colorMapping[5], // Blue
colorMapping[8], // Purple
colorMapping[8], // Purple
colorMapping[8], // Purple
colorMapping[13], // Gray
colorMapping[4], // Green
colorMapping[3], // Lime
colorMapping[2], // Yellow
colorMapping[4], // Green
colorMapping[7], // Light Blue
colorMapping[7] // Light Blue
};
BLOCK_MATERIALS = new ArrayList<Material>();
ITEM_MATERIALS = new ArrayList<Material>();
Inventory tempInventory = Bukkit.createInventory(null, 9);
for (Material mat : Material.values()) {
// Verify an ItemStack of the material can be placed into an inventory. In 1.12 and up this can easily be checked with mat.isItem(), but that doesn't exist pre-1.12
tempInventory.clear();
tempInventory.setItem(0, new ItemStack(mat, 1));
ItemStack itemStack = tempInventory.getItem(0);
if (itemStack != null) {
if (mat.isBlock()) {
BLOCK_MATERIALS.add(mat);
} else if (!mat.isBlock()) {
ITEM_MATERIALS.add(mat);
}
}
}
}
public GuiInventoryEditData(PPlayer pplayer, ParticlePair editingParticle, List<GuiInventoryEditFinishedCallback> callbackList, int callbackListPosition) {
super(pplayer, Bukkit.createInventory(pplayer.getPlayer(), INVENTORY_SIZE, LangManager.getText(Lang.GUI_SELECT_DATA)));
ParticleEffect pe = editingParticle.getEffect();
if (pe.hasProperty(ParticleProperty.COLORABLE)) {
if (pe == ParticleEffect.NOTE) { // Note data
this.populateNoteData(editingParticle, callbackList, callbackListPosition);
} else { // Color data
this.populateColorData(editingParticle, callbackList, callbackListPosition);
}
} else if (pe.hasProperty(ParticleProperty.REQUIRES_MATERIAL_DATA)) {
if (pe == ParticleEffect.ITEM) { // Item data
this.populateItemData(editingParticle, callbackList, callbackListPosition);
} else { // Block data
this.populateBlockData(editingParticle, callbackList, callbackListPosition);
}
}
// Back Button
GuiActionButton backButton = new GuiActionButton(INVENTORY_SIZE - 1, GuiIcon.BACK.get(), LangManager.getText(Lang.GUI_COLOR_INFO) + LangManager.getText(Lang.GUI_BACK_BUTTON), new String[] {}, (button, isShiftClick) -> {
callbackList.get(callbackListPosition - 1).execute();
});
this.actionButtons.add(backButton);
this.populate();
}
/**
* Populates the Inventory with available color data options
*
* @param editingParticle The ParticlePair that's being edited
* @param callbackList The List of GuiInventoryEditFinishedCallbacks
* @param callbackListPosition The index of the callbackList we're currently at
*/
private void populateColorData(ParticlePair editingParticle, List<GuiInventoryEditFinishedCallback> callbackList, int callbackListPosition) {
int index = 10;
int nextWrap = 17;
for (int i = 0; i < colorMapping.length; i++) {
ColorData colorData = colorMapping[i];
String formattedDisplayColor = ChatColor.RED.toString() + colorData.getOrdinaryColor().getRed() + " " + ChatColor.GREEN + colorData.getOrdinaryColor().getGreen() + " " + ChatColor.AQUA + colorData.getOrdinaryColor().getBlue();
// Color Data Buttons
GuiActionButton setColorButton = new GuiActionButton(index,
colorData,
colorData.getName(),
new String[] { LangManager.getText(Lang.GUI_COLOR_INFO) + LangManager.getText(Lang.GUI_SELECT_DATA_DESCRIPTION, formattedDisplayColor) },
(button, isShiftClick) -> {
editingParticle.setColor(colorData.getOrdinaryColor());
callbackList.get(callbackListPosition + 1).execute();
});
this.actionButtons.add(setColorButton);
index++;
if (index == nextWrap) { // Loop around border
nextWrap += 9;
index += 2;
}
}
// Rainbow Color Data Button
GuiActionButton setRainbowColorButton = new GuiActionButton(39,
rainbowColorMapping,
LangManager.getText(Lang.GUI_COLOR_ICON_NAME) + LangManager.getText(Lang.RAINBOW),
new String[] { LangManager.getText(Lang.GUI_COLOR_INFO) + LangManager.getText(Lang.GUI_SELECT_DATA_DESCRIPTION, LangManager.getText(Lang.RAINBOW)) },
(button, isShiftClick) -> {
editingParticle.setColor(new OrdinaryColor(999, 999, 999));
callbackList.get(callbackListPosition + 1).execute();
});
this.actionButtons.add(setRainbowColorButton);
// Rainbow Color Data Button
List<ColorData> randomizedColorsList = Arrays.asList(colorMapping.clone());
Collections.shuffle(randomizedColorsList);
ColorData[] randomizedColors = new ColorData[randomizedColorsList.size()];
randomizedColors = randomizedColorsList.toArray(randomizedColors);
GuiActionButton setRandomColorButton = new GuiActionButton(41,
randomizedColors,
LangManager.getText(Lang.GUI_COLOR_ICON_NAME) + LangManager.getText(Lang.RANDOM),
new String[] { LangManager.getText(Lang.GUI_COLOR_INFO) + LangManager.getText(Lang.GUI_SELECT_DATA_DESCRIPTION, LangManager.getText(Lang.RANDOM)) },
(button, isShiftClick) -> {
editingParticle.setColor(new OrdinaryColor(998, 998, 998));
callbackList.get(callbackListPosition + 1).execute();
});
this.actionButtons.add(setRandomColorButton);
}
/**
* Populates the Inventory with available note data options
*
* @param editingParticle The ParticlePair that's being edited
* @param callbackList The List of GuiInventoryEditFinishedCallbacks
* @param callbackListPosition The index of the callbackList we're currently at
*/
private void populateNoteData(ParticlePair editingParticle, List<GuiInventoryEditFinishedCallback> callbackList, int callbackListPosition) {
for (int i = 0; i < noteColorMapping.length; i++) {
ColorData colorData = noteColorMapping[i];
String formattedDisplayName = LangManager.getText(Lang.GUI_COLOR_ICON_NAME) + LangManager.getText(Lang.GUI_SELECT_DATA_NOTE, i) + " (" + colorData.getName() + LangManager.getText(Lang.GUI_COLOR_ICON_NAME) + ")";
String formattedDescription = LangManager.getText(Lang.GUI_COLOR_INFO) + LangManager.getText(Lang.GUI_SELECT_DATA_DESCRIPTION, LangManager.getText(Lang.GUI_SELECT_DATA_NOTE, i));
// Note Color Buttons
int noteIndex = i;
GuiActionButton setColorButton = new GuiActionButton(i,
colorData,
formattedDisplayName,
new String[] { formattedDescription },
(button, isShiftClick) -> {
editingParticle.setNoteColor(new NoteColor(noteIndex));
callbackList.get(callbackListPosition + 1).execute();
});
this.actionButtons.add(setColorButton);
}
// Rainbow Note Data Button
GuiActionButton setRainbowColorButton = new GuiActionButton(39,
rainbowColorMapping,
LangManager.getText(Lang.GUI_COLOR_ICON_NAME) + LangManager.getText(Lang.RAINBOW),
new String[] { LangManager.getText(Lang.GUI_COLOR_INFO) + LangManager.getText(Lang.GUI_SELECT_DATA_DESCRIPTION, LangManager.getText(Lang.RAINBOW)) },
(button, isShiftClick) -> {
editingParticle.setNoteColor(new NoteColor(99));
callbackList.get(callbackListPosition + 1).execute();
});
this.actionButtons.add(setRainbowColorButton);
// Rainbow Note Data Button
List<ColorData> randomizedColorsList = Arrays.asList(colorMapping.clone());
Collections.shuffle(randomizedColorsList);
ColorData[] randomizedColors = new ColorData[randomizedColorsList.size()];
randomizedColors = randomizedColorsList.toArray(randomizedColors);
GuiActionButton setRandomColorButton = new GuiActionButton(41,
randomizedColors,
LangManager.getText(Lang.GUI_COLOR_ICON_NAME) + LangManager.getText(Lang.RANDOM),
new String[] { LangManager.getText(Lang.GUI_COLOR_INFO) + LangManager.getText(Lang.GUI_SELECT_DATA_DESCRIPTION, LangManager.getText(Lang.RANDOM)) },
(button, isShiftClick) -> {
editingParticle.setNoteColor(new NoteColor(98));
callbackList.get(callbackListPosition + 1).execute();
});
this.actionButtons.add(setRandomColorButton);
}
/**
* Populates the Inventory with available item data options
*
* @param editingParticle The ParticlePair that's being edited
* @param callbackList The List of GuiInventoryEditFinishedCallbacks
* @param callbackListPosition The index of the callbackList we're currently at
*/
private void populateItemData(ParticlePair editingParticle, List<GuiInventoryEditFinishedCallback> callbackList, int callbackListPosition) {
List<Material> materialBag = new ArrayList<Material>();
while (materialBag.size() < 36) { // Grab 36 random materials that are an item
Material randomMaterial = ITEM_MATERIALS.get(RANDOM.nextInt(ITEM_MATERIALS.size()));
if (!materialBag.contains(randomMaterial)) materialBag.add(randomMaterial);
}
for (int i = 0; i < materialBag.size(); i++) {
// Item Data Button
Material material = materialBag.get(i);
GuiActionButton setRainbowColorButton = new GuiActionButton(i,
material,
LangManager.getText(Lang.GUI_COLOR_ICON_NAME) + material.name().toLowerCase(),
new String[] { LangManager.getText(Lang.GUI_COLOR_INFO) + LangManager.getText(Lang.GUI_SELECT_DATA_DESCRIPTION, material.name().toLowerCase()) },
(button, isShiftClick) -> {
editingParticle.setItemMaterial(material);
callbackList.get(callbackListPosition + 1).execute();
});
this.actionButtons.add(setRainbowColorButton);
}
// Randomize Button, re-randomizes the icons
GuiActionButton randomizeButton = new GuiActionButton(45,
GuiIcon.RANDOMIZE.get(),
LangManager.getText(Lang.GUI_COLOR_ICON_NAME) + LangManager.getText(Lang.GUI_SELECT_DATA_RANDOMIZE_ITEMS),
new String[] { LangManager.getText(Lang.GUI_COLOR_SUBTEXT) + LangManager.getText(Lang.GUI_SELECT_DATA_RANDOMIZE_ITEMS_DESCRIPTION) },
(block, isShiftClick) -> {
callbackList.get(callbackListPosition).execute(); // Just reopen the same inventory
});
this.actionButtons.add(randomizeButton);
}
/**
* Populates the Inventory with available block data options
*
* @param editingParticle The ParticlePair that's being edited
* @param callbackList The List of GuiInventoryEditFinishedCallbacks
* @param callbackListPosition The index of the callbackList we're currently at
*/
private void populateBlockData(ParticlePair editingParticle, List<GuiInventoryEditFinishedCallback> callbackList, int callbackListPosition) {
List<Material> materialBag = new ArrayList<Material>();
while (materialBag.size() < 36) { // Grab 36 random materials that are an item
Material randomMaterial = BLOCK_MATERIALS.get(RANDOM.nextInt(BLOCK_MATERIALS.size()));
if (!materialBag.contains(randomMaterial)) materialBag.add(randomMaterial);
}
for (int i = 0; i < materialBag.size(); i++) {
// Item Data Button
Material material = materialBag.get(i);
GuiActionButton setRainbowColorButton = new GuiActionButton(i,
material,
LangManager.getText(Lang.GUI_COLOR_ICON_NAME) + material.name().toLowerCase(),
new String[] { LangManager.getText(Lang.GUI_COLOR_INFO) + LangManager.getText(Lang.GUI_SELECT_DATA_DESCRIPTION, material.name().toLowerCase()) },
(button, isShiftClick) -> {
editingParticle.setBlockMaterial(material);
callbackList.get(callbackListPosition + 1).execute();
});
this.actionButtons.add(setRainbowColorButton);
}
// Randomize Button, re-randomizes the icons
GuiActionButton randomizeButton = new GuiActionButton(45,
GuiIcon.RANDOMIZE.get(),
LangManager.getText(Lang.GUI_COLOR_ICON_NAME) + LangManager.getText(Lang.GUI_SELECT_DATA_RANDOMIZE_BLOCKS),
new String[] { LangManager.getText(Lang.GUI_COLOR_SUBTEXT) + LangManager.getText(Lang.GUI_SELECT_DATA_RANDOMIZE_BLOCKS_DESCRIPTION) },
(block, isShiftClick) -> {
callbackList.get(callbackListPosition).execute(); // Just reopen the same inventory
});
this.actionButtons.add(randomizeButton);
}
/**
* A data class used for storing information about the color data
*/
protected static class ColorData {
private DyeColor dyeColor;
private Material material;
private OrdinaryColor ordinaryColor;
private Lang name;
public ColorData(DyeColor dyeColor, Material material, OrdinaryColor ordinaryColor, Lang name) {
this.dyeColor = dyeColor;
this.material = material;
this.ordinaryColor = ordinaryColor;
this.name = name;
}
/**
* Get the DyeColor
*
* @return The DyeColor
*/
public DyeColor getDyeColor() {
return this.dyeColor;
}
/**
* Get the Material representing this color
*
* @return The Material
*/
public Material getMaterial() {
return this.material;
}
/**
* Get the OrdinaryColor representing this color
*
* @return The OrdinaryColor
*/
public OrdinaryColor getOrdinaryColor() {
return this.ordinaryColor;
}
/**
* Get the name of this color
*
* @return The name of this color
*/
public String getName() {
return LangManager.getText(this.name);
}
}
}

View file

@ -0,0 +1,44 @@
package com.esophose.playerparticles.gui;
import java.util.List;
import org.bukkit.Bukkit;
import com.esophose.playerparticles.manager.LangManager;
import com.esophose.playerparticles.manager.LangManager.Lang;
import com.esophose.playerparticles.manager.PermissionManager;
import com.esophose.playerparticles.manager.SettingManager.GuiIcon;
import com.esophose.playerparticles.particles.PPlayer;
import com.esophose.playerparticles.particles.ParticleEffect;
import com.esophose.playerparticles.particles.ParticlePair;
public class GuiInventoryEditEffect extends GuiInventory {
public GuiInventoryEditEffect(PPlayer pplayer, ParticlePair editingParticle, List<GuiInventoryEditFinishedCallback> callbackList, int callbackListPosition) {
super(pplayer, Bukkit.createInventory(pplayer.getPlayer(), INVENTORY_SIZE, LangManager.getText(Lang.GUI_SELECT_EFFECT)));
// Select Effect Buttons
List<ParticleEffect> effectsUserHasPermissionFor = PermissionManager.getEffectsUserHasPermissionFor(pplayer.getPlayer());
for (int i = 0; i < effectsUserHasPermissionFor.size(); i++) {
ParticleEffect effect = effectsUserHasPermissionFor.get(i);
GuiActionButton selectButton = new GuiActionButton(i,
GuiIcon.EFFECT.get(effect.getName()),
LangManager.getText(Lang.GUI_COLOR_ICON_NAME) + effect.getName(),
new String[] { LangManager.getText(Lang.GUI_COLOR_INFO) + LangManager.getText(Lang.GUI_SELECT_EFFECT_DESCRIPTION, effect.getName()) },
(button, isShiftClick) -> {
editingParticle.setEffect(effect);
callbackList.get(callbackListPosition + 1).execute();
});
this.actionButtons.add(selectButton);
}
// Back Button
GuiActionButton backButton = new GuiActionButton(INVENTORY_SIZE - 1, GuiIcon.BACK.get(), LangManager.getText(Lang.GUI_COLOR_INFO) + LangManager.getText(Lang.GUI_BACK_BUTTON), new String[] {}, (button, isShiftClick) -> {
callbackList.get(callbackListPosition - 1).execute();
});
this.actionButtons.add(backButton);
this.populate();
}
}

View file

@ -0,0 +1,127 @@
package com.esophose.playerparticles.gui;
import java.util.ArrayList;
import java.util.List;
import org.bukkit.Bukkit;
import com.esophose.playerparticles.manager.DataManager;
import com.esophose.playerparticles.manager.LangManager;
import com.esophose.playerparticles.manager.LangManager.Lang;
import com.esophose.playerparticles.manager.SettingManager.GuiIcon;
import com.esophose.playerparticles.particles.PPlayer;
import com.esophose.playerparticles.particles.ParticleEffect.ParticleProperty;
import com.esophose.playerparticles.particles.ParticleGroup;
import com.esophose.playerparticles.particles.ParticlePair;
public class GuiInventoryEditParticle extends GuiInventory {
public GuiInventoryEditParticle(PPlayer pplayer, ParticlePair editingParticle) {
super(pplayer, Bukkit.createInventory(pplayer.getPlayer(), INVENTORY_SIZE, LangManager.getText(Lang.GUI_EDITING_PARTICLE, editingParticle.getId())));
this.fillBorder(BorderColor.RED);
// Particle Info Icon
String particleInfo = LangManager.getText(Lang.GUI_PARTICLE_INFO, editingParticle.getId(), editingParticle.getEffect().getName(), editingParticle.getStyle().getName(), editingParticle.getDataString());
GuiActionButton particleInfoIcon = new GuiActionButton(13,
GuiIcon.PARTICLES.get(),
LangManager.getText(Lang.GUI_COLOR_ICON_NAME) + LangManager.getText(Lang.GUI_PARTICLE_NAME, editingParticle.getId()),
new String[] { LangManager.getText(Lang.GUI_COLOR_INFO) + particleInfo },
(button, isShiftClick) -> {});
this.actionButtons.add(particleInfoIcon);
// Edit Effect Button
GuiActionButton editEffectButton = new GuiActionButton(38,
GuiIcon.EDIT_EFFECT.get(),
LangManager.getText(Lang.GUI_COLOR_ICON_NAME) + LangManager.getText(Lang.GUI_EDIT_EFFECT),
new String[] { LangManager.getText(Lang.GUI_COLOR_SUBTEXT) + LangManager.getText(Lang.GUI_EDIT_EFFECT_DESCRIPTION) },
(button, isShiftClick) -> {
List<GuiInventoryEditFinishedCallback> callbacks = new ArrayList<GuiInventoryEditFinishedCallback>();
callbacks.add(() -> GuiHandler.transition(new GuiInventoryEditParticle(pplayer, editingParticle)));
callbacks.add(() -> GuiHandler.transition(new GuiInventoryEditEffect(pplayer, editingParticle, callbacks, 1)));
callbacks.add(() -> {
ParticleGroup group = pplayer.getActiveParticleGroup();
for (ParticlePair particle : group.getParticles()) {
if (particle.getId() == editingParticle.getId()) {
particle.setEffect(editingParticle.getEffect());
break;
}
}
DataManager.saveParticleGroup(pplayer.getUniqueId(), group);
GuiHandler.transition(new GuiInventoryEditParticle(pplayer, editingParticle));
});
callbacks.get(1).execute();
});
this.actionButtons.add(editEffectButton);
// Edit Style Button
GuiActionButton editStyleButton = new GuiActionButton(40,
GuiIcon.EDIT_STYLE.get(),
LangManager.getText(Lang.GUI_COLOR_ICON_NAME) + LangManager.getText(Lang.GUI_EDIT_STYLE),
new String[] { LangManager.getText(Lang.GUI_COLOR_SUBTEXT) + LangManager.getText(Lang.GUI_EDIT_STYLE_DESCRIPTION) },
(button, isShiftClick) -> {
List<GuiInventoryEditFinishedCallback> callbacks = new ArrayList<GuiInventoryEditFinishedCallback>();
callbacks.add(() -> GuiHandler.transition(new GuiInventoryEditParticle(pplayer, editingParticle)));
callbacks.add(() -> GuiHandler.transition(new GuiInventoryEditStyle(pplayer, editingParticle, callbacks, 1)));
callbacks.add(() -> {
ParticleGroup group = pplayer.getActiveParticleGroup();
for (ParticlePair particle : group.getParticles()) {
if (particle.getId() == editingParticle.getId()) {
particle.setStyle(editingParticle.getStyle());
break;
}
}
DataManager.saveParticleGroup(pplayer.getUniqueId(), group);
GuiHandler.transition(new GuiInventoryEditParticle(pplayer, editingParticle));
});
callbacks.get(1).execute();
});
this.actionButtons.add(editStyleButton);
// Edit Data Button
boolean usesData = editingParticle.getEffect().hasProperty(ParticleProperty.COLORABLE) || editingParticle.getEffect().hasProperty(ParticleProperty.REQUIRES_MATERIAL_DATA);
GuiActionButton editDataButton = new GuiActionButton(42,
GuiIcon.EDIT_DATA.get(),
LangManager.getText(Lang.GUI_COLOR_ICON_NAME) + LangManager.getText(Lang.GUI_EDIT_DATA),
usesData ? new String[] { LangManager.getText(Lang.GUI_COLOR_SUBTEXT) + LangManager.getText(Lang.GUI_EDIT_DATA_DESCRIPTION) } :
new String[] { LangManager.getText(Lang.GUI_COLOR_UNAVAILABLE) + LangManager.getText(Lang.GUI_EDIT_DATA_UNAVAILABLE) },
(button, isShiftClick) -> {
if (usesData) {
List<GuiInventoryEditFinishedCallback> callbacks = new ArrayList<GuiInventoryEditFinishedCallback>();
callbacks.add(() -> GuiHandler.transition(new GuiInventoryEditParticle(pplayer, editingParticle)));
callbacks.add(() -> GuiHandler.transition(new GuiInventoryEditData(pplayer, editingParticle, callbacks, 1)));
callbacks.add(() -> {
ParticleGroup group = pplayer.getActiveParticleGroup();
for (ParticlePair particle : group.getParticles()) {
if (particle.getId() == editingParticle.getId()) {
particle.setColor(editingParticle.getColor());
particle.setNoteColor(editingParticle.getNoteColor());
particle.setItemMaterial(editingParticle.getItemMaterial());
particle.setBlockMaterial(editingParticle.getBlockMaterial());
break;
}
}
DataManager.saveParticleGroup(pplayer.getUniqueId(), group);
GuiHandler.transition(new GuiInventoryEditParticle(pplayer, editingParticle));
});
callbacks.get(1).execute();
}
});
this.actionButtons.add(editDataButton);
// Back Button
GuiActionButton backButton = new GuiActionButton(INVENTORY_SIZE - 1, GuiIcon.BACK.get(), LangManager.getText(Lang.GUI_COLOR_INFO) + LangManager.getText(Lang.GUI_BACK_BUTTON), new String[] {}, (button, isShiftClick) -> {
GuiHandler.transition(new GuiInventoryManageParticles(pplayer));
});
this.actionButtons.add(backButton);
this.populate();
}
}

View file

@ -0,0 +1,44 @@
package com.esophose.playerparticles.gui;
import java.util.List;
import org.bukkit.Bukkit;
import com.esophose.playerparticles.manager.LangManager;
import com.esophose.playerparticles.manager.LangManager.Lang;
import com.esophose.playerparticles.manager.PermissionManager;
import com.esophose.playerparticles.manager.SettingManager.GuiIcon;
import com.esophose.playerparticles.particles.PPlayer;
import com.esophose.playerparticles.particles.ParticlePair;
import com.esophose.playerparticles.styles.api.ParticleStyle;
public class GuiInventoryEditStyle extends GuiInventory {
public GuiInventoryEditStyle(PPlayer pplayer, ParticlePair editingParticle, List<GuiInventoryEditFinishedCallback> callbackList, int callbackListPosition) {
super(pplayer, Bukkit.createInventory(pplayer.getPlayer(), INVENTORY_SIZE, LangManager.getText(Lang.GUI_SELECT_STYLE)));
// Select Style Buttons
List<ParticleStyle> stylesUserHasPermissionFor = PermissionManager.getStylesUserHasPermissionFor(pplayer.getPlayer());
for (int i = 0; i < stylesUserHasPermissionFor.size(); i++) {
ParticleStyle style = stylesUserHasPermissionFor.get(i);
GuiActionButton selectButton = new GuiActionButton(i,
GuiIcon.STYLE.get(style.getName()),
LangManager.getText(Lang.GUI_COLOR_ICON_NAME) + style.getName(),
new String[] { LangManager.getText(Lang.GUI_COLOR_INFO) + LangManager.getText(Lang.GUI_SELECT_EFFECT_DESCRIPTION, style.getName()) },
(button, isShiftClick) -> {
editingParticle.setStyle(style);
callbackList.get(callbackListPosition + 1).execute();
});
this.actionButtons.add(selectButton);
}
// Back Button
GuiActionButton backButton = new GuiActionButton(INVENTORY_SIZE - 1, GuiIcon.BACK.get(), LangManager.getText(Lang.GUI_COLOR_INFO) + LangManager.getText(Lang.GUI_BACK_BUTTON), new String[] {}, (button, isShiftClick) -> {
callbackList.get(callbackListPosition - 1).execute();
});
this.actionButtons.add(backButton);
this.populate();
}
}

View file

@ -0,0 +1,72 @@
package com.esophose.playerparticles.gui;
import java.util.Comparator;
import java.util.List;
import java.util.Map.Entry;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import com.esophose.playerparticles.manager.DataManager;
import com.esophose.playerparticles.manager.LangManager;
import com.esophose.playerparticles.manager.LangManager.Lang;
import com.esophose.playerparticles.manager.SettingManager.GuiIcon;
import com.esophose.playerparticles.particles.PPlayer;
import com.esophose.playerparticles.particles.ParticleGroup;
import com.esophose.playerparticles.particles.ParticlePair;
public class GuiInventoryLoadPresetGroups extends GuiInventory {
public GuiInventoryLoadPresetGroups(PPlayer pplayer) {
super(pplayer, Bukkit.createInventory(pplayer.getPlayer(), INVENTORY_SIZE, LangManager.getText(Lang.GUI_LOAD_A_PRESET_GROUP)));
this.fillBorder(BorderColor.GREEN);
int index = 10;
int nextWrap = 17;
int maxIndex = 43;
List<Entry<ParticleGroup, Material>> groups = ParticleGroup.getPresetGroupsForGUIForPlayer(pplayer.getPlayer());
for (Entry<ParticleGroup, Material> groupEntry : groups) {
ParticleGroup group = groupEntry.getKey();
Material iconMaterial = groupEntry.getValue();
List<ParticlePair> particles = group.getParticles();
particles.sort(Comparator.comparingInt(ParticlePair::getId));
String[] lore = new String[particles.size() + 1];
lore[0] = LangManager.getText(Lang.GUI_COLOR_SUBTEXT) + LangManager.getText(Lang.GUI_CLICK_TO_LOAD, particles.size());
int i = 1;
for (ParticlePair particle : particles) {
lore[i] = LangManager.getText(Lang.GUI_COLOR_INFO) + LangManager.getText(Lang.GUI_PARTICLE_INFO, particle.getId(), particle.getEffect().getName(), particle.getStyle().getName(), particle.getDataString());
i++;
}
// Load Group Buttons
GuiActionButton groupButton = new GuiActionButton(index, iconMaterial, LangManager.getText(Lang.GUI_COLOR_ICON_NAME) + group.getName(), lore, (button, isShiftClick) -> {
ParticleGroup activeGroup = pplayer.getActiveParticleGroup();
activeGroup.getParticles().clear();
for (ParticlePair particle : particles)
activeGroup.getParticles().add(particle.clone());
DataManager.saveParticleGroup(pplayer.getUniqueId(), activeGroup);
pplayer.getPlayer().closeInventory();
});
this.actionButtons.add(groupButton);
index++;
if (index == nextWrap) { // Loop around border
nextWrap += 9;
index += 2;
}
if (index > maxIndex) break; // Overflowed the available space
}
// Back Button
GuiActionButton backButton = new GuiActionButton(INVENTORY_SIZE - 1, GuiIcon.BACK.get(), LangManager.getText(Lang.GUI_COLOR_INFO) + LangManager.getText(Lang.GUI_BACK_BUTTON), new String[] {}, (button, isShiftClick) -> {
GuiHandler.transition(new GuiInventoryDefault(pplayer));
});
this.actionButtons.add(backButton);
this.populate();
}
}

View file

@ -0,0 +1,91 @@
package com.esophose.playerparticles.gui;
import java.util.Comparator;
import java.util.List;
import org.bukkit.Bukkit;
import com.esophose.playerparticles.manager.DataManager;
import com.esophose.playerparticles.manager.LangManager;
import com.esophose.playerparticles.manager.LangManager.Lang;
import com.esophose.playerparticles.manager.SettingManager.GuiIcon;
import com.esophose.playerparticles.particles.PPlayer;
import com.esophose.playerparticles.particles.ParticleGroup;
import com.esophose.playerparticles.particles.ParticlePair;
public class GuiInventoryManageGroups extends GuiInventory {
public GuiInventoryManageGroups(PPlayer pplayer) {
super(pplayer, Bukkit.createInventory(pplayer.getPlayer(), INVENTORY_SIZE, LangManager.getText(Lang.GUI_MANAGE_YOUR_GROUPS)));
this.fillBorder(BorderColor.BROWN);
int index = 10;
int nextWrap = 17;
int maxIndex = 35;
List<ParticleGroup> groups = pplayer.getParticleGroups();
groups.sort(Comparator.comparing(ParticleGroup::getName));
for (ParticleGroup group : groups) {
if (group.getName().equals(ParticleGroup.DEFAULT_NAME)) continue;
List<ParticlePair> particles = group.getParticles();
particles.sort(Comparator.comparingInt(ParticlePair::getId));
String[] lore = new String[particles.size() + 2];
lore[0] = LangManager.getText(Lang.GUI_COLOR_SUBTEXT) + LangManager.getText(Lang.GUI_CLICK_TO_LOAD, particles.size());
int i = 1;
for (ParticlePair particle : particles) {
lore[i] = LangManager.getText(Lang.GUI_COLOR_INFO) + LangManager.getText(Lang.GUI_PARTICLE_INFO, particle.getId(), particle.getEffect().getName(), particle.getStyle().getName(), particle.getDataString());
i++;
}
lore[i] = LangManager.getText(Lang.GUI_COLOR_UNAVAILABLE) + LangManager.getText(Lang.GUI_SHIFT_CLICK_TO_DELETE);
// Load Group Buttons
GuiActionButton groupButton = new GuiActionButton(index, GuiIcon.GROUPS.get(), LangManager.getText(Lang.GUI_COLOR_ICON_NAME) + group.getName(), lore, (button, isShiftClick) -> {
if (isShiftClick) {
DataManager.removeParticleGroup(pplayer.getUniqueId(), group);
this.actionButtons.remove(button);
this.inventory.setItem(button.getSlot(), null);
} else {
ParticleGroup activeGroup = pplayer.getActiveParticleGroup();
activeGroup.getParticles().clear();
for (ParticlePair particle : particles)
activeGroup.getParticles().add(particle.clone());
DataManager.saveParticleGroup(pplayer.getUniqueId(), activeGroup);
pplayer.getPlayer().closeInventory();
}
});
this.actionButtons.add(groupButton);
index++;
if (index == nextWrap) { // Loop around border
nextWrap += 9;
index += 2;
}
if (index > maxIndex) break; // Overflowed the available space
}
// Save Group Button
GuiActionButton saveGroupButton = new GuiActionButton(40,
GuiIcon.CREATE.get(),
LangManager.getText(Lang.GUI_COLOR_ICON_NAME) + LangManager.getText(Lang.GUI_SAVE_GROUP),
new String[] {
LangManager.getText(Lang.GUI_COLOR_INFO) + LangManager.getText(Lang.GUI_SAVE_GROUP_DESCRIPTION),
LangManager.getText(Lang.GUI_COLOR_SUBTEXT) + LangManager.getText(Lang.GUI_SAVE_GROUP_DESCRIPTION_2),
},
(button, isShiftClick) -> {}); // Does nothing on click
this.actionButtons.add(saveGroupButton);
// Back Button
GuiActionButton backButton = new GuiActionButton(INVENTORY_SIZE - 1, GuiIcon.BACK.get(), LangManager.getText(Lang.GUI_COLOR_INFO) + LangManager.getText(Lang.GUI_BACK_BUTTON), new String[] {}, (button, isShiftClick) -> {
GuiHandler.transition(new GuiInventoryDefault(pplayer));
});
this.actionButtons.add(backButton);
this.populate();
}
}

View file

@ -0,0 +1,128 @@
package com.esophose.playerparticles.gui;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import org.bukkit.Bukkit;
import com.esophose.playerparticles.manager.DataManager;
import com.esophose.playerparticles.manager.LangManager;
import com.esophose.playerparticles.manager.PermissionManager;
import com.esophose.playerparticles.manager.LangManager.Lang;
import com.esophose.playerparticles.manager.SettingManager.GuiIcon;
import com.esophose.playerparticles.particles.PPlayer;
import com.esophose.playerparticles.particles.ParticleGroup;
import com.esophose.playerparticles.particles.ParticlePair;
import com.esophose.playerparticles.particles.ParticleEffect.ParticleProperty;
public class GuiInventoryManageParticles extends GuiInventory {
public GuiInventoryManageParticles(PPlayer pplayer) {
super(pplayer, Bukkit.createInventory(pplayer.getPlayer(), INVENTORY_SIZE, LangManager.getText(Lang.GUI_MANAGE_YOUR_PARTICLES)));
this.fillBorder(BorderColor.ORANGE);
// Manage/Delete Particle Buttons
List<ParticlePair> particles = pplayer.getActiveParticles();
particles.sort(Comparator.comparingInt(ParticlePair::getId));
int index = 10;
int nextWrap = 17;
int maxIndex = 35;
for (ParticlePair particle : particles) {
GuiActionButton selectButton = new GuiActionButton(index,
GuiIcon.PARTICLES.get(),
LangManager.getText(Lang.GUI_COLOR_ICON_NAME) + LangManager.getText(Lang.GUI_PARTICLE_NAME, particle.getId()),
new String[] {
LangManager.getText(Lang.GUI_COLOR_SUBTEXT) + LangManager.getText(Lang.GUI_CLICK_TO_EDIT_PARTICLE, particles.size()),
LangManager.getText(Lang.GUI_COLOR_INFO) + LangManager.getText(Lang.GUI_PARTICLE_INFO, particle.getId(), particle.getEffect().getName(), particle.getStyle().getName(), particle.getDataString()),
LangManager.getText(Lang.GUI_COLOR_UNAVAILABLE) + LangManager.getText(Lang.GUI_SHIFT_CLICK_TO_DELETE)
},
(button, isShiftClick) -> {
if (!isShiftClick) {
GuiHandler.transition(new GuiInventoryEditParticle(pplayer, particle));
} else {
// Delete particle
ParticleGroup activeGroup = pplayer.getActiveParticleGroup();
for (ParticlePair pp : activeGroup.getParticles()) {
if (pp.getId() == particle.getId()) {
activeGroup.getParticles().remove(pp);
break;
}
}
DataManager.saveParticleGroup(pplayer.getUniqueId(), activeGroup);
// Update inventory to reflect deletion
this.actionButtons.remove(button);
this.inventory.setItem(button.getSlot(), null);
}
});
this.actionButtons.add(selectButton);
index++;
if (index == nextWrap) { // Loop around border
nextWrap += 9;
index += 2;
}
if (index > maxIndex) break; // Overflowed the available space
}
// Create New Particle Button
boolean canCreate = pplayer.getActiveParticles().size() < PermissionManager.getMaxParticlesAllowed(pplayer.getPlayer());
String lore = LangManager.getText(Lang.GUI_COLOR_INFO) + LangManager.getText(Lang.GUI_CREATE_PARTICLE_DESCRIPTION);
GuiActionButton createNewParticle = new GuiActionButton(38,
GuiIcon.CREATE.get(),
LangManager.getText(Lang.GUI_COLOR_ICON_NAME) + LangManager.getText(Lang.GUI_CREATE_PARTICLE),
canCreate ? new String[] { lore } : new String[] { lore, LangManager.getText(Lang.GUI_COLOR_UNAVAILABLE) + LangManager.getText(Lang.GUI_CREATE_PARTICLE_UNAVAILABLE) },
(button, isShiftClick) -> {
if (!canCreate) return;
ParticlePair editingParticle = ParticlePair.getNextDefault(pplayer);
List<GuiInventoryEditFinishedCallback> callbacks = new ArrayList<GuiInventoryEditFinishedCallback>();
callbacks.add(() -> GuiHandler.transition(new GuiInventoryManageParticles(pplayer)));
callbacks.add(() -> GuiHandler.transition(new GuiInventoryEditEffect(pplayer, editingParticle, callbacks, 1)));
callbacks.add(() -> GuiHandler.transition(new GuiInventoryEditStyle(pplayer, editingParticle, callbacks, 2)));
callbacks.add(() -> {
if (editingParticle.getEffect().hasProperty(ParticleProperty.COLORABLE) || editingParticle.getEffect().hasProperty(ParticleProperty.REQUIRES_MATERIAL_DATA)) {
GuiHandler.transition(new GuiInventoryEditData(pplayer, editingParticle, callbacks, 3));
} else {
callbacks.get(4).execute();
}
});
callbacks.add(() -> {
// Save new particle
ParticleGroup group = pplayer.getActiveParticleGroup();
group.getParticles().add(editingParticle);
DataManager.saveParticleGroup(pplayer.getUniqueId(), group);
// Reopen the manage particle inventory
GuiHandler.transition(new GuiInventoryManageParticles(pplayer));
});
callbacks.get(1).execute();
});
this.actionButtons.add(createNewParticle);
// Reset Particles Button
GuiActionButton resetParticles = new GuiActionButton(42,
GuiIcon.RESET.get(),
LangManager.getText(Lang.GUI_COLOR_ICON_NAME) + LangManager.getText(Lang.GUI_RESET_PARTICLES),
new String[] { LangManager.getText(Lang.GUI_COLOR_UNAVAILABLE) + LangManager.getText(Lang.GUI_RESET_PARTICLES_DESCRIPTION) },
(button, isShiftClick) -> {
// Reset particles
DataManager.saveParticleGroup(pplayer.getUniqueId(), ParticleGroup.getDefaultGroup());
// Reopen this same inventory to refresh it
GuiHandler.transition(new GuiInventoryManageParticles(pplayer));
});
this.actionButtons.add(resetParticles);
// Back Button
GuiActionButton backButton = new GuiActionButton(INVENTORY_SIZE - 1, GuiIcon.BACK.get(), LangManager.getText(Lang.GUI_COLOR_INFO) + LangManager.getText(Lang.GUI_BACK_BUTTON), new String[] {}, (button, isShiftClick) -> {
GuiHandler.transition(new GuiInventoryDefault(pplayer));
});
this.actionButtons.add(backButton);
this.populate();
}
}

View file

@ -1,833 +0,0 @@
/**
* 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.List;
import java.util.Map;
import java.util.Random;
import java.util.UUID;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Color;
import org.bukkit.DyeColor;
import org.bukkit.Material;
import org.bukkit.Particle;
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.InventoryView;
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.scheduler.BukkitRunnable;
import com.esophose.playerparticles.PPlayer;
import com.esophose.playerparticles.PlayerParticles;
import com.esophose.playerparticles.manager.PPlayerDataManager;
import com.esophose.playerparticles.manager.MessageManager.MessageType;
import com.esophose.playerparticles.particles.ParticleEffect;
import com.esophose.playerparticles.particles.ParticleEffect.BlockData;
import com.esophose.playerparticles.particles.ParticleEffect.ItemData;
import com.esophose.playerparticles.particles.ParticleEffect.NoteColor;
import com.esophose.playerparticles.particles.ParticleEffect.OrdinaryColor;
import com.esophose.playerparticles.particles.ParticleEffect.ParticleProperty;
import com.esophose.playerparticles.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 ColorData[] colorMapping;
/**
* 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;
/**
* Cached material data
*/
private static final Random RANDOM = new Random();
private static List<Material> BLOCK_MATERIALS = new ArrayList<Material>();
private static List<Material> ITEM_MATERIALS = new ArrayList<Material>();
static { // @formatter:off
colorMapping = new ColorData[] {
new ColorData(DyeColor.RED, ParticleUtils.closestMatch("ROSE_RED"), new OrdinaryColor(255, 0, 0), ChatColor.RED + "red"),
new ColorData(DyeColor.ORANGE, ParticleUtils.closestMatch("ORANGE_DYE"), new OrdinaryColor(255, 140, 0), ChatColor.GOLD + "orange"),
new ColorData(DyeColor.YELLOW, ParticleUtils.closestMatch("DANDELION_YELLOW"), new OrdinaryColor(255, 255, 0), ChatColor.YELLOW + "yellow"),
new ColorData(DyeColor.LIME, ParticleUtils.closestMatch("LIME_DYE"), new OrdinaryColor(50, 205, 50), ChatColor.GREEN + "lime green"),
new ColorData(DyeColor.GREEN, ParticleUtils.closestMatch("CACTUS_GREEN"), new OrdinaryColor(0, 128, 0), ChatColor.DARK_GREEN + "green"),
new ColorData(DyeColor.BLUE, ParticleUtils.closestMatch("LAPIZ_LAZULI"), new OrdinaryColor(0, 0, 255), ChatColor.DARK_BLUE + "blue"),
new ColorData(DyeColor.CYAN, ParticleUtils.closestMatch("CYAN_DYE"), new OrdinaryColor(0, 139, 139), ChatColor.DARK_AQUA + "cyan"),
new ColorData(DyeColor.LIGHT_BLUE, ParticleUtils.closestMatch("LIGHT_BLUE_DYE"), new OrdinaryColor(173, 216, 230), ChatColor.AQUA + "light blue"),
new ColorData(DyeColor.PURPLE, ParticleUtils.closestMatch("PURPLE_DYE"), new OrdinaryColor(138, 43, 226), ChatColor.DARK_PURPLE + "purple"),
new ColorData(DyeColor.MAGENTA, ParticleUtils.closestMatch("MAGENTA_DYE"), new OrdinaryColor(202, 31, 123), ChatColor.LIGHT_PURPLE + "magenta"),
new ColorData(DyeColor.PINK, ParticleUtils.closestMatch("PINK_DYE"), new OrdinaryColor(255, 182, 193), ChatColor.LIGHT_PURPLE + "pink"),
new ColorData(DyeColor.BROWN, ParticleUtils.closestMatch("COCOA_BEANS"), new OrdinaryColor(139, 69, 19), ChatColor.GOLD + "brown"),
new ColorData(DyeColor.BLACK, ParticleUtils.closestMatch("INK_SAC"), new OrdinaryColor(0, 0, 0), ChatColor.DARK_GRAY + "black"),
new ColorData(DyeColor.GRAY, ParticleUtils.closestMatch("GRAY_DYE"), new OrdinaryColor(128, 128, 128), ChatColor.DARK_GRAY + "gray"),
new ColorData(DyeColor.getByDyeData((byte)7), ParticleUtils.closestMatch("LIGHT_GRAY_DYE"), new OrdinaryColor(192, 192, 192), ChatColor.GRAY + "light gray"),
new ColorData(DyeColor.WHITE, ParticleUtils.closestMatch("BONE_MEAL"), new OrdinaryColor(255, 255, 255), ChatColor.WHITE + "white"),
};
rainbowColors = new DyeColor[] {
DyeColor.RED,
DyeColor.ORANGE,
DyeColor.YELLOW,
DyeColor.LIME,
DyeColor.LIGHT_BLUE,
DyeColor.BLUE,
DyeColor.PURPLE
};
Inventory testingInventory = Bukkit.createInventory(null, 9);
for (Material mat : Material.values()) {
// Verify an ItemStack of the material can be placed into an inventory. In 1.12 and up this can easily be checked with mat.isItem(), but that doesn't exist pre 1.12
testingInventory.clear();
testingInventory.setItem(0, new ItemStack(mat, 1));
ItemStack itemStack = testingInventory.getItem(0);
if (itemStack != null) {
if (mat.isBlock()) {
BLOCK_MATERIALS.add(mat);
} else if (!mat.isBlock()) {
ITEM_MATERIALS.add(mat);
}
}
}
} // @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.closestMatchWithFallback(config.getString("gui-icon.main-menu.EFFECT"));
defaultMenuIcons[1] = ParticleUtils.closestMatchWithFallback(config.getString("gui-icon.main-menu.STYLE"));
defaultMenuIcons[2] = ParticleUtils.closestMatchWithFallback(config.getString("gui-icon.main-menu.DATA"));
// Grab a different effect icon set based on if the Minecraft version is >= 1.13 or not
String legacy;
try {
Particle.valueOf("NAUTILUS");
legacy = "";
} catch (Exception ex) {
legacy = "-legacy";
}
for (ParticleEffect effect : ParticleEffect.getSupportedEffects()) {
String effectName = effect.getName().toUpperCase();
Material iconMaterial = ParticleUtils.closestMatchWithFallback(config.getString("gui-icon.effect" + legacy + "." + effectName));
effectIcons.put(effectName, iconMaterial);
}
for (ParticleStyle style : ParticleStyleManager.getStyles()) {
String styleName = style.getName().toUpperCase();
Material iconMaterial = ParticleUtils.closestMatchWithFallback(config.getString("gui-icon.style" + legacy + "." + styleName));
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 playerGuiInventoriesd
*/
public void run() {
List<UUID> toRemoveList = new ArrayList<UUID>();
for (Map.Entry<UUID, GuiInventory> entry : playerGuiInventories.entrySet()) {
UUID playerUUID = entry.getKey();
PPlayer pplayer = PPlayerDataManager.getInstance().getPPlayer(playerUUID);
if (pplayer == null) {
toRemoveList.add(playerUUID);
continue;
}
Player player = Bukkit.getPlayer(playerUUID);
if (player == null) {
toRemoveList.add(playerUUID);
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;
}
/**
* Forcefully closes all open PlayerParticles GUIs
* Used for when the plugin unloads so players can't take items from the GUI
*/
public static void forceCloseAllOpenGUIs() {
for (Player p : Bukkit.getOnlinePlayers()) {
InventoryView openInventory = p.getOpenInventory();
if (openInventory == null) continue;
Inventory topInventory = openInventory.getTopInventory();
if (topInventory == null) continue;
// Check if any of the inventories are the one the user has open, close if true
for (GuiInventory guiInventory : playerGuiInventories.values()) {
if (topInventory.equals(guiInventory.getInventory())) {
p.closeInventory();
break;
}
}
}
}
/**
* 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 ((state == GuiState.EFFECT && PermissionManager.getEffectsUserHasPermissionFor(player).size() == 1) ||
(state == GuiState.STYLE && 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().equals(guiInventory.getInventory())) {
player.openInventory(guiInventory.getInventory());
}
} 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;
Material playerHead = ParticleUtils.closestMatch("PLAYER_HEAD");
if (playerHead != null) {
currentIcon = new ItemStack(playerHead, 1);
} else {
currentIcon = new ItemStack(ParticleUtils.closestMatch("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());
//currentIconMeta.setOwningPlayer(Bukkit.getOfflinePlayer(player.getUniqueId())); // This doesn't exist in 1.9
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)) // @formatter:off
if (pe == ParticleEffect.NOTE) dataType = "note " + dataType;
else dataType = "color " + dataType;
else if (pe.hasProperty(ParticleProperty.REQUIRES_MATERIAL_DATA)) if (pe == ParticleEffect.ITEM) dataType = "item " + dataType;
else dataType = "block " + dataType; // @formatter:on
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_MATERIAL_DATA)) {
List<Material> materialBag = new ArrayList<Material>();
int materialIndex = 0;
if (pe == ParticleEffect.ITEM) { // Item data
Material currentItemMaterial = p.getItemData().getMaterial();
while (materialBag.size() < 28) { // Grab 28 random materials that are an item
Material randomMaterial = ITEM_MATERIALS.get(RANDOM.nextInt(ITEM_MATERIALS.size()));
if (!materialBag.contains(randomMaterial))
materialBag.add(randomMaterial);
}
for (int i = 10; i <= 16; i++) { // Top row
inventory.setItem(i, getItemForMaterialData(currentItemMaterial, "item", materialBag.get(materialIndex)));
materialIndex++;
}
for (int i = 19; i <= 25; i++) { // Middle 1 row
inventory.setItem(i, getItemForMaterialData(currentItemMaterial, "item", materialBag.get(materialIndex)));
materialIndex++;
}
for (int i = 28; i <= 34; i++) { // Middle 2 row
inventory.setItem(i, getItemForMaterialData(currentItemMaterial, "item", materialBag.get(materialIndex)));
materialIndex++;
}
for (int i = 37; i <= 43; i++) { // Bottom row
inventory.setItem(i, getItemForMaterialData(currentItemMaterial, "item", materialBag.get(materialIndex)));
materialIndex++;
}
} else { // Block data
Material currentBlockMaterial = p.getBlockData().getMaterial();
while (materialBag.size() < 28) { // Grab 28 random materials that are an item
Material randomMaterial = BLOCK_MATERIALS.get(RANDOM.nextInt(BLOCK_MATERIALS.size()));
if (!materialBag.contains(randomMaterial))
materialBag.add(randomMaterial);
}
for (int i = 10; i <= 16; i++) { // Top row
inventory.setItem(i, getItemForMaterialData(currentBlockMaterial, "block", materialBag.get(materialIndex)));
materialIndex++;
}
for (int i = 19; i <= 25; i++) { // Middle 1 row
inventory.setItem(i, getItemForMaterialData(currentBlockMaterial, "block", materialBag.get(materialIndex)));
materialIndex++;
}
for (int i = 28; i <= 34; i++) { // Middle 2 row
inventory.setItem(i, getItemForMaterialData(currentBlockMaterial, "block", materialBag.get(materialIndex)));
materialIndex++;
}
for (int i = 37; i <= 43; i++) { // Bottom row
inventory.setItem(i, getItemForMaterialData(currentBlockMaterial, "block", materialBag.get(materialIndex)));
materialIndex++;
}
}
}
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 (isGuiDisabled()) return; // Don't worry about processing anything if the GUI is disabled
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
e.setCancelled(true); // In the PlayerParticles GUI, can't let them take anything out
if (!guiInventory.getInventory().equals(e.getClickedInventory())) return; // Clicked bottom inventory
PPlayer pplayer = PPlayerDataManager.getInstance().getPPlayer(player.getUniqueId());
if (pplayer == null) {
player.closeInventory();
return;
}
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:
PPlayerDataManager.getInstance().savePPlayer(pplayer.getUniqueId(), ParticleManager.effectFromString(name));
changeState(pplayer, GuiState.DEFAULT);
break;
case STYLE:
PPlayerDataManager.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)) {
PPlayerDataManager.getInstance().savePPlayer(pplayer.getUniqueId(), new NoteColor(99));
} else {
int note = Integer.parseInt(ChatColor.stripColor(clicked.getItemMeta().getDisplayName()).substring(6));
PPlayerDataManager.getInstance().savePPlayer(pplayer.getUniqueId(), new NoteColor(note));
}
} else {
if (clicked.getItemMeta().getDisplayName().equals(rainbowName)) {
PPlayerDataManager.getInstance().savePPlayer(pplayer.getUniqueId(), new OrdinaryColor(999, 999, 999));
} else {
for (int i = 0; i < colorMapping.length; i++) {
if (clicked.getItemMeta().getDisplayName().equals(colorMapping[i].getName())) {
PPlayerDataManager.getInstance().savePPlayer(pplayer.getUniqueId(), colorMapping[i].getOrdinaryColor());
}
}
}
}
} else if (pe.hasProperty(ParticleProperty.REQUIRES_MATERIAL_DATA)) {
Material clickedMaterial = clicked.getType(); // All preset materials have a data value of 0
if (pe == ParticleEffect.ITEM) {
PPlayerDataManager.getInstance().savePPlayer(pplayer.getUniqueId(), new ItemData(clickedMaterial));
} else {
PPlayerDataManager.getInstance().savePPlayer(pplayer.getUniqueId(), new BlockData(clickedMaterial));
}
}
changeState(pplayer, GuiState.DEFAULT);
break;
}
}
/**
* 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) {
ColorData colorData = colorMapping[colorIndex];
String formattedDisplayColor = ChatColor.RED.toString() + colorData.getOrdinaryColor().getRed() + " " + ChatColor.GREEN + colorData.getOrdinaryColor().getGreen() + " " + ChatColor.AQUA + colorData.getOrdinaryColor().getBlue();
ItemStack colorIcon;
if (colorData.getMaterial() != null) { // Use 1.13 materials
colorIcon = new ItemStack(colorData.getMaterial());
} else { // Use < 1.13 dye colors
colorIcon = new Dye(colorData.getDyeColor()).toItemStack(1);
}
ItemMeta colorIconMeta = colorIcon.getItemMeta();
colorIconMeta.setDisplayName(colorData.getName());
if (!currentColor.equals(colorData.getOrdinaryColor())) {
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) {
ColorData colorData = getColorDataFromOrdinaryColor(dyeColor);
ItemStack rainbowIcon;
if (colorData.getMaterial() != null) { // Use 1.13 materials
rainbowIcon = new ItemStack(colorData.getMaterial());
} else { // Use < 1.13 dye colors
rainbowIcon = new Dye(colorData.getDyeColor()).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) {
ColorData colorData = getColorDataFromOrdinaryColor(dyeColor);
ItemStack rainbowIcon;
if (colorData.getMaterial() != null) { // Use 1.13 materials
rainbowIcon = new ItemStack(colorData.getMaterial());
} else { // Use < 1.13 dye colors
rainbowIcon = new Dye(colorData.getDyeColor()).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;
}
/**
* Gets a ColorData object from its DyeColor
*
* @param color The DyeColor
* @return The found ColorData object, null if not found
*/
private static ColorData getColorDataFromOrdinaryColor(DyeColor color) {
for (ColorData colorData : colorMapping)
if (colorData.getDyeColor().equals(color))
return colorData;
return null;
}
}

View file

@ -0,0 +1,482 @@
package com.esophose.playerparticles.manager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import org.bukkit.Material;
import org.bukkit.scheduler.BukkitRunnable;
import com.esophose.playerparticles.PlayerParticles;
import com.esophose.playerparticles.particles.FixedParticleEffect;
import com.esophose.playerparticles.particles.PPlayer;
import com.esophose.playerparticles.particles.ParticleEffect;
import com.esophose.playerparticles.particles.ParticleEffect.NoteColor;
import com.esophose.playerparticles.particles.ParticleEffect.OrdinaryColor;
import com.esophose.playerparticles.particles.ParticleGroup;
import com.esophose.playerparticles.particles.ParticlePair;
import com.esophose.playerparticles.styles.api.ParticleStyle;
import com.esophose.playerparticles.util.ParticleUtils;
/**
* All data changes to PPlayers such as group or fixed effect changes must be done through here,
* rather than directly on the PPlayer object
*/
public class DataManager {
private DataManager() {
}
/**
* Gets a PPlayer from cache
* This method should be used over the other one unless you absolutely need the PPlayer and you don't care about waiting
* You should always check for a null result when using this method
*
* @param playerUUID The PPlayer to get
* @return The PPlayer from cache
*/
public static PPlayer getPPlayer(UUID playerUUID) {
for (PPlayer pp : ParticleManager.particlePlayers)
if (pp.getUniqueId().equals(playerUUID)) return pp;
return null;
}
/**
* Gets a player from the save data, creates one if it doesn't exist and caches it
*
* @param playerUUID The pplayer to get
* @param callback The callback to execute with the found pplayer, or a newly generated one
*/
public static void getPPlayer(UUID playerUUID, ConfigurationCallback<PPlayer> callback) {
// Try to get them from cache first
PPlayer fromCache = getPPlayer(playerUUID);
if (fromCache != null) {
callback.execute(fromCache);
return;
}
async(() -> {
List<ParticleGroup> groups = new ArrayList<ParticleGroup>();
List<FixedParticleEffect> fixedParticles = new ArrayList<FixedParticleEffect>();
PlayerParticles.getDBConnector().connect((connection) -> {
// Load particle groups
String groupQuery = "SELECT * FROM pp_group g " + // @formatter:off
"JOIN pp_particle p ON g.uuid = p.group_uuid " +
"WHERE g.owner_uuid = ?"; // @formatter:on
try (PreparedStatement statement = connection.prepareStatement(groupQuery)) {
statement.setString(1, playerUUID.toString());
ResultSet result = statement.executeQuery();
while (result.next()) {
// Group properties
String groupName = result.getString("name");
// Particle properties
int id = result.getInt("id");
ParticleEffect effect = ParticleEffect.fromName(result.getString("effect"));
ParticleStyle style = ParticleStyle.fromName(result.getString("style"));
Material itemMaterial = ParticleUtils.closestMatchWithFallback(result.getString("item_material"));
Material blockMaterial = ParticleUtils.closestMatchWithFallback(result.getString("block_material"));
NoteColor noteColor = new NoteColor(result.getInt("note"));
OrdinaryColor color = new OrdinaryColor(result.getInt("r"), result.getInt("g"), result.getInt("b"));
ParticlePair particle = new ParticlePair(playerUUID, id, effect, style, itemMaterial, blockMaterial, color, noteColor);
// Try to add particle to an existing group
boolean groupAlreadyExists = false;
for (ParticleGroup group : groups) {
if (group.getName().equalsIgnoreCase(groupName)) {
group.getParticles().add(particle);
groupAlreadyExists = true;
break;
}
}
// Add the particle to a new group if one didn't already exist
if (!groupAlreadyExists) {
List<ParticlePair> particles = new ArrayList<ParticlePair>();
particles.add(particle);
ParticleGroup newGroup = new ParticleGroup(groupName, particles);
groups.add(newGroup);
}
}
}
// Load fixed effects
String fixedQuery = "SELECT f.id AS f_id, f.world, f.xPos, f.yPos, f.zPos, p.id AS p_id, p.effect, p.style, p.item_material, p.block_material, p.note, p.r, p.g, p.b FROM pp_fixed f " + // @formatter:off
"JOIN pp_particle p ON f.particle_uuid = p.uuid " +
"WHERE f.owner_uuid = ?"; // @formatter:on
try (PreparedStatement statement = connection.prepareStatement(fixedQuery)) {
statement.setString(1, playerUUID.toString());
ResultSet result = statement.executeQuery();
while (result.next()) {
// Fixed effect properties
int fixedEffectId = result.getInt("f_id");
String worldName = result.getString("world");
double xPos = result.getDouble("xPos");
double yPos = result.getDouble("yPos");
double zPos = result.getDouble("zPos");
// Particle properties
int particleId = result.getInt("p_id");
ParticleEffect effect = ParticleEffect.fromName(result.getString("effect"));
ParticleStyle style = ParticleStyle.fromName(result.getString("style"));
Material itemMaterial = ParticleUtils.closestMatchWithFallback(result.getString("item_material"));
Material blockMaterial = ParticleUtils.closestMatchWithFallback(result.getString("block_material"));
NoteColor noteColor = new NoteColor(result.getInt("note"));
OrdinaryColor color = new OrdinaryColor(result.getInt("r"), result.getInt("g"), result.getInt("b"));
ParticlePair particle = new ParticlePair(playerUUID, particleId, effect, style, itemMaterial, blockMaterial, color, noteColor);
fixedParticles.add(new FixedParticleEffect(playerUUID, fixedEffectId, worldName, xPos, yPos, zPos, particle));
}
}
// If there aren't any groups then this is a brand new PPlayer and we need to save a new active group for them
boolean activeGroupExists = false;
for (ParticleGroup group : groups) {
if (group.getName().equals(ParticleGroup.DEFAULT_NAME)) {
activeGroupExists = true;
break;
}
}
if (!activeGroupExists) {
ParticleGroup activeGroup = new ParticleGroup(ParticleGroup.DEFAULT_NAME, new ArrayList<ParticlePair>());
saveParticleGroup(playerUUID, activeGroup);
groups.add(activeGroup);
}
final PPlayer loadedPPlayer = new PPlayer(playerUUID, groups, fixedParticles);
sync(() -> {
if (getPPlayer(playerUUID) == null) { // Make sure the PPlayer still isn't added, since this is async it's possible it got ran twice
ParticleManager.particlePlayers.add(loadedPPlayer);
callback.execute(loadedPPlayer);
}
});
});
});
}
/**
* Loads all PPlayers from the database that own FixedParticleEffects
*/
public static void loadFixedEffects() {
async(() -> {
PlayerParticles.getDBConnector().connect((connection) -> {
String query = "SELECT DISTINCT owner_uuid FROM pp_fixed";
try (PreparedStatement statement = connection.prepareStatement(query)) {
ResultSet result = statement.executeQuery();
while (result.next()) {
UUID playerUUID = UUID.fromString(result.getString("owner_uuid"));
sync(() -> {
getPPlayer(playerUUID, (pplayer) -> { });
});
}
}
});
});
}
/**
* Saves a ParticleGroup. If it already exists, update it.
*
* @param playerUUID The owner of the group
* @param group The group to create/update
*/
public static void saveParticleGroup(UUID playerUUID, ParticleGroup group) {
async(() -> {
PlayerParticles.getDBConnector().connect((connection) -> {
String groupUUIDQuery = "SELECT uuid FROM pp_group WHERE owner_uuid = ? AND name = ?";
try (PreparedStatement statement = connection.prepareStatement(groupUUIDQuery)) {
statement.setString(1, playerUUID.toString());
statement.setString(2, group.getName());
String groupUUID = null;
ResultSet result = statement.executeQuery();
if (result.next()) { // Clear out particles from existing group
groupUUID = result.getString("uuid");
String particlesDeleteQuery = "DELETE FROM pp_particle WHERE group_uuid = ?";
PreparedStatement particlesDeleteStatement = connection.prepareStatement(particlesDeleteQuery);
particlesDeleteStatement.setString(1, result.getString("uuid"));
particlesDeleteStatement.executeUpdate();
} else { // Create new group
groupUUID = UUID.randomUUID().toString();
String groupCreateQuery = "INSERT INTO pp_group (uuid, owner_uuid, name) VALUES (?, ?, ?)";
PreparedStatement groupCreateStatement = connection.prepareStatement(groupCreateQuery);
groupCreateStatement.setString(1, groupUUID);
groupCreateStatement.setString(2, playerUUID.toString());
groupCreateStatement.setString(3, group.getName());
groupCreateStatement.executeUpdate();
}
// Fill group with new particles
String createParticlesQuery = "INSERT INTO pp_particle (uuid, group_uuid, id, effect, style, item_material, block_material, note, r, g, b) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
PreparedStatement particlesStatement = connection.prepareStatement(createParticlesQuery);
for (ParticlePair particle : group.getParticles()) {
particlesStatement.setString(1, UUID.randomUUID().toString());
particlesStatement.setString(2, groupUUID);
particlesStatement.setInt(3, particle.getId());
particlesStatement.setString(4, particle.getEffect().getName());
particlesStatement.setString(5, particle.getStyle().getName());
particlesStatement.setString(6, particle.getItemMaterial().name());
particlesStatement.setString(7, particle.getBlockMaterial().name());
particlesStatement.setInt(8, particle.getNoteColor().getNote());
particlesStatement.setInt(9, particle.getColor().getRed());
particlesStatement.setInt(10, particle.getColor().getGreen());
particlesStatement.setInt(11, particle.getColor().getBlue());
particlesStatement.addBatch();
}
particlesStatement.executeBatch();
}
});
});
getPPlayer(playerUUID, (pplayer) -> {
for (ParticleGroup existing : pplayer.getParticleGroups()) {
if (group.getName().equalsIgnoreCase(existing.getName())) {
pplayer.getParticleGroups().remove(existing);
break;
}
}
pplayer.getParticleGroups().add(group);
});
}
/**
* Removes a ParticleGroup
*
* @param playerUUID The owner of the group
* @param group The group to remove
*/
public static void removeParticleGroup(UUID playerUUID, ParticleGroup group) {
async(() -> {
PlayerParticles.getDBConnector().connect((connection) -> {
String groupQuery = "SELECT * FROM pp_group WHERE owner_uuid = ? AND name = ?";
String particleDeleteQuery = "DELETE FROM pp_particle WHERE group_uuid = ?";
String groupDeleteQuery = "DELETE FROM pp_group WHERE uuid = ?";
// Execute group uuid query
String groupUUID = null;
try (PreparedStatement statement = connection.prepareStatement(groupQuery)) {
statement.setString(1, playerUUID.toString());
statement.setString(2, group.getName());
ResultSet result = statement.executeQuery();
if (result.next()) {
groupUUID = result.getString("uuid");
}
}
// Execute particle delete update
try (PreparedStatement statement = connection.prepareStatement(particleDeleteQuery)) {
statement.setString(1, groupUUID);
statement.executeUpdate();
}
// Execute group delete update
try (PreparedStatement statement = connection.prepareStatement(groupDeleteQuery)) {
statement.setString(1, groupUUID);
statement.executeUpdate();
}
});
});
getPPlayer(playerUUID, (pplayer) -> {
pplayer.getParticleGroups().remove(group);
});
}
/**
* Saves a fixed effect to save data
* Does not perform a check to see if a fixed effect with this id already exists
*
* @param fixedEffect The fixed effect to save
*/
public static void saveFixedEffect(FixedParticleEffect fixedEffect) {
async(() -> {
PlayerParticles.getDBConnector().connect((connection) -> {
String particleUUID = UUID.randomUUID().toString();
String particleQuery = "INSERT INTO pp_particle (uuid, group_uuid, id, effect, style, item_material, block_material, note, r, g, b) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
try (PreparedStatement statement = connection.prepareStatement(particleQuery)) {
ParticlePair particle = fixedEffect.getParticlePair();
statement.setString(1, particleUUID);
statement.setNull(2, java.sql.Types.VARCHAR);
statement.setInt(3, fixedEffect.getId());
statement.setString(4, particle.getEffect().getName());
statement.setString(5, particle.getStyle().getName());
statement.setString(6, particle.getItemMaterial().name());
statement.setString(7, particle.getBlockMaterial().name());
statement.setInt(8, particle.getNoteColor().getNote());
statement.setInt(9, particle.getColor().getRed());
statement.setInt(10, particle.getColor().getGreen());
statement.setInt(11, particle.getColor().getBlue());
statement.executeUpdate();
}
String fixedEffectQuery = "INSERT INTO pp_fixed (owner_uuid, id, particle_uuid, world, xPos, yPos, zPos) VALUES (?, ?, ?, ?, ?, ?, ?)";
try (PreparedStatement statement = connection.prepareStatement(fixedEffectQuery)) {
statement.setString(1, fixedEffect.getOwnerUniqueId().toString());
statement.setInt(2, fixedEffect.getId());
statement.setString(3, particleUUID);
statement.setString(4, fixedEffect.getLocation().getWorld().getName());
statement.setDouble(5, fixedEffect.getLocation().getX());
statement.setDouble(6, fixedEffect.getLocation().getY());
statement.setDouble(7, fixedEffect.getLocation().getZ());
statement.executeUpdate();
}
});
});
getPPlayer(fixedEffect.getOwnerUniqueId(), (pplayer) -> {
pplayer.addFixedEffect(fixedEffect);
});
}
/**
* Updates a fixed effect's particle values
*
* @param fixedEffect The fixed effect to update
*/
public static void updateFixedEffect(FixedParticleEffect fixedEffect) {
async(() -> {
PlayerParticles.getDBConnector().connect((connection) -> {
// Update fixed effect
String fixedEffectQuery = "UPDATE pp_fixed SET xPos = ?, yPos = ?, zPos = ? WHERE owner_uuid = ? AND id = ?";
try (PreparedStatement statement = connection.prepareStatement(fixedEffectQuery)) {
statement.setDouble(1, fixedEffect.getLocation().getX());
statement.setDouble(2, fixedEffect.getLocation().getY());
statement.setDouble(3, fixedEffect.getLocation().getZ());
statement.setString(4, fixedEffect.getOwnerUniqueId().toString());
statement.setInt(5, fixedEffect.getId());
statement.executeUpdate();
}
// Update particle
String particleUpdateQuery = "UPDATE pp_particle " +
"SET effect = ?, style = ?, item_material = ?, block_material = ?, note = ?, r = ?, g = ?, b = ? " +
"WHERE uuid = (SELECT particle_uuid FROM pp_fixed WHERE owner_uuid = ? AND id = ?)";
try (PreparedStatement statement = connection.prepareStatement(particleUpdateQuery)) {
ParticlePair particle = fixedEffect.getParticlePair();
statement.setString(1, particle.getEffect().getName());
statement.setString(2, particle.getStyle().getName());
statement.setString(3, particle.getItemMaterial().name());
statement.setString(4, particle.getBlockMaterial().name());
statement.setInt(5, particle.getNoteColor().getNote());
statement.setInt(6, particle.getColor().getRed());
statement.setInt(7, particle.getColor().getGreen());
statement.setInt(8, particle.getColor().getBlue());
statement.setString(9, fixedEffect.getOwnerUniqueId().toString());
statement.setInt(10, fixedEffect.getId());
statement.executeUpdate();
}
});
});
getPPlayer(fixedEffect.getOwnerUniqueId(), (pplayer) -> {
pplayer.removeFixedEffect(fixedEffect.getId());
pplayer.addFixedEffect(fixedEffect);
});
}
/**
* Deletes a fixed effect from save data
* Does not perform a check to see if a fixed effect with this id already exists
*
* @param playerUUID The player who owns the effect
* @param id The id of the effect to remove
*/
public static void removeFixedEffect(UUID playerUUID, int id) {
async(() -> {
PlayerParticles.getDBConnector().connect((connection) -> {
String particleUUID = null;
String particleUUIDQuery = "SELECT particle_uuid FROM pp_fixed WHERE owner_uuid = ? AND id = ?";
try (PreparedStatement statement = connection.prepareStatement(particleUUIDQuery)) {
statement.setString(1, playerUUID.toString());
statement.setInt(2, id);
ResultSet result = statement.executeQuery();
if (result.next()) {
particleUUID = result.getString("particle_uuid");
}
}
String particleDeleteQuery = "DELETE FROM pp_particle WHERE uuid = ?";
try (PreparedStatement statement = connection.prepareStatement(particleDeleteQuery)) {
statement.setString(1, particleUUID);
statement.executeUpdate();
}
String fixedEffectDeleteQuery = "DELETE FROM pp_fixed WHERE owner_uuid = ? AND id = ?";
try (PreparedStatement statement = connection.prepareStatement(fixedEffectDeleteQuery)) {
statement.setString(1, playerUUID.toString());
statement.setInt(2, id);
statement.executeUpdate();
}
});
});
getPPlayer(playerUUID, (pplayer) -> {
pplayer.removeFixedEffect(id);
});
}
/**
* Asynchronizes the callback with it's own thread
*
* @param asyncCallback The callback to run on a separate thread
*/
private static void async(SyncInterface asyncCallback) {
new BukkitRunnable() {
public void run() {
asyncCallback.execute();
}
}.runTaskAsynchronously(PlayerParticles.getPlugin());
}
/**
* Synchronizes the callback with the main thread
*
* @param syncCallback The callback to run on the main thread
*/
private static void sync(SyncInterface syncCallback) {
new BukkitRunnable() {
public void run() {
syncCallback.execute();
}
}.runTask(PlayerParticles.getPlugin());
}
/**
* Provides an easy way to run a section of code either synchronously or asynchronously using a callback
*/
@FunctionalInterface
private static interface SyncInterface {
public void execute();
}
/**
* Allows callbacks to be passed between configuration methods and executed for returning objects after database queries
*/
@FunctionalInterface
public static interface ConfigurationCallback<T> {
public void execute(T obj);
}
}

View file

@ -1,114 +0,0 @@
package com.esophose.playerparticles.manager;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import org.bukkit.configuration.file.FileConfiguration;
import com.esophose.playerparticles.PlayerParticles;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
public class DatabaseManager {
private HikariDataSource hikari;
private boolean initializedSuccessfully = false;
public DatabaseManager(FileConfiguration pluginConfig) {
String hostname = pluginConfig.getString("database-hostname");
String port = pluginConfig.getString("database-port");
String database = pluginConfig.getString("database-name");
String user = pluginConfig.getString("database-user-name");
String pass = pluginConfig.getString("database-user-password");
HikariConfig config = new HikariConfig();
config.setJdbcUrl("jdbc:mysql://" + hostname + ":" + port + "/" + database);
config.setUsername(user);
config.setPassword(pass);
config.setMaximumPoolSize(5);
try {
hikari = new HikariDataSource(config);
initializedSuccessfully = true;
} catch (Exception ex) {
initializedSuccessfully = false;
}
}
/**
* Checks if the connection to the database has been created
*
* @return If the connection is created or not
*/
public boolean isInitialized() {
return initializedSuccessfully;
}
/**
* Closes all connections to the database
*/
public void closeConnection() {
hikari.close();
}
/**
* Executes a callback with a Connection passed and automatically closes it
*
* @param callback The callback to execute once the connection is retrieved
*/
public void connect(ConnectionCallback callback) {
try (Connection connection = hikari.getConnection()) {
callback.execute(connection);
} catch (SQLException ex) {
PlayerParticles.getPlugin().getLogger().warning("An error occurred retrieving a database connection: " + ex.getMessage());
}
}
/**
* Executes an update statement and cleans up all resources
*
* @param query The update statement to run
* @return An int with the status of the first statement in the query
* @throws SQLException If an SQL problem occurs executing the statement
*/
public int updateSQL(String query) throws SQLException {
Connection connection = null;
Statement statement = null;
try {
connection = hikari.getConnection();
statement = connection.createStatement();
int[] results;
if (query.indexOf(';') != -1) {
String[] queries = query.split(";");
for (String q : queries) {
statement.addBatch(q);
}
results = statement.executeBatch();
} else {
results = new int[] { statement.executeUpdate(query) };
}
statement.close();
return results[0];
} catch (SQLException ex) {
throw ex;
} finally {
try { if (connection != null) connection.close(); } catch (Exception ex) { };
try { if (statement != null) statement.close(); } catch (Exception ex) { };
}
}
/**
* Allows Lambda expressions to be used to reduce duplicated code for getting connections
*/
public static interface ConnectionCallback {
public void execute(Connection connection) throws SQLException;
}
}

View file

@ -0,0 +1,458 @@
package com.esophose.playerparticles.manager;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.text.MessageFormat;
import org.bukkit.ChatColor;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player;
import com.esophose.playerparticles.PlayerParticles;
import com.esophose.playerparticles.manager.SettingManager.PSetting;
import com.esophose.playerparticles.particles.PPlayer;
public class LangManager {
/**
* Contains the location in the .lang file of every chat message
*/
public static enum Lang { // @formatter:off
// Command Errors
COMMAND_ERROR_NO_EFFECTS,
COMMAND_ERROR_UNKNOWN,
// Command Descriptions
COMMAND_DESCRIPTION_ADD,
COMMAND_DESCRIPTION_DATA,
COMMAND_DESCRIPTION_DEFAULT,
COMMAND_DESCRIPTION_EDIT,
COMMAND_DESCRIPTION_EFFECT,
COMMAND_DESCRIPTION_EFFECTS,
COMMAND_DESCRIPTION_FIXED,
COMMAND_DESCRIPTION_GROUP,
COMMAND_DESCRIPTION_GUI,
COMMAND_DESCRIPTION_HELP,
COMMAND_DESCRIPTION_INFO,
COMMAND_DESCRIPTION_LIST,
COMMAND_DESCRIPTION_RELOAD,
COMMAND_DESCRIPTION_REMOVE,
COMMAND_DESCRIPTION_RESET,
COMMAND_DESCRIPTION_STYLE,
COMMAND_DESCRIPTION_STYLES,
COMMAND_DESCRIPTION_VERSION,
COMMAND_DESCRIPTION_WORLDS,
// Sub-Command Usage
COMMAND_DESCRIPTION_FIXED_CREATE,
COMMAND_DESCRIPTION_FIXED_EDIT,
COMMAND_DESCRIPTION_FIXED_REMOVE,
COMMAND_DESCRIPTION_FIXED_LIST,
COMMAND_DESCRIPTION_FIXED_INFO,
COMMAND_DESCRIPTION_FIXED_CLEAR,
COMMAND_DESCRIPTION_GROUP_SAVE,
COMMAND_DESCRIPTION_GROUP_LOAD,
COMMAND_DESCRIPTION_GROUP_REMOVE,
COMMAND_DESCRIPTION_GROUP_LIST,
COMMAND_DESCRIPTION_GROUP_INFO,
// ID Lookup
ID_INVALID,
ID_UNKNOWN,
// Add Command
ADD_REACHED_MAX,
ADD_PARTICLE_APPLIED,
// Data Command
DATA_NO_ARGS,
// Edit Command
EDIT_INVALID_PROPERTY,
EDIT_SUCCESS_EFFECT,
EDIT_SUCCESS_STYLE,
EDIT_SUCCESS_DATA,
// Group Command
GROUP_INVALID,
GROUP_PRESET_NO_PERMISSION,
GROUP_RESERVED,
GROUP_NO_NAME,
GROUP_SAVE_REACHED_MAX,
GROUP_SAVE_NO_PARTICLES,
GROUP_SAVE_SUCCESS,
GROUP_SAVE_SUCCESS_OVERWRITE,
GROUP_LOAD_SUCCESS,
GROUP_LOAD_PRESET_SUCCESS,
GROUP_REMOVE_PRESET,
GROUP_REMOVE_SUCCESS,
GROUP_INFO_HEADER,
GROUP_LIST_NONE,
GROUP_LIST_OUTPUT,
GROUP_LIST_PRESETS,
// Reload Command
RELOAD_SUCCESS,
RELOAD_NO_PERMISSION,
// Remove Command
REMOVE_NO_ARGS,
REMOVE_SUCCESS,
// List Command
LIST_NONE,
LIST_YOU_HAVE,
LIST_OUTPUT,
// Rainbow
RAINBOW,
// Random
RANDOM,
// Effects
EFFECT_NO_PERMISSION,
EFFECT_INVALID,
EFFECT_LIST,
EFFECT_LIST_EMPTY,
// Styles
STYLE_NO_PERMISSION,
STYLE_EVENT_SPAWNING_INFO,
STYLE_INVALID,
STYLE_LIST,
// Data
DATA_USAGE_NONE,
DATA_USAGE_BLOCK,
DATA_USAGE_ITEM,
DATA_USAGE_COLOR,
DATA_USAGE_NOTE,
DATA_INVALID_BLOCK,
DATA_INVALID_ITEM,
DATA_INVALID_COLOR,
DATA_INVALID_NOTE,
DATA_INVALID_MATERIAL_NOT_ITEM,
DATA_INVALID_MATERIAL_NOT_BLOCK,
DATA_INVALID_MATERIAL_ITEM,
DATA_INVALID_MATERIAL_BLOCK,
// Worlds
DISABLED_WORLDS,
DISABLED_WORLDS_NONE,
// Reset
RESET_SUCCESS,
// Fixed Effects
FIXED_CREATE_MISSING_ARGS,
FIXED_CREATE_INVALID_COORDS,
FIXED_CREATE_OUT_OF_RANGE,
FIXED_CREATE_LOOKING_TOO_FAR,
FIXED_CREATE_EFFECT_INVALID,
FIXED_CREATE_EFFECT_NO_PERMISSION,
FIXED_CREATE_STYLE_INVALID,
FIXED_CREATE_STYLE_NO_PERMISSION,
FIXED_CREATE_STYLE_NON_FIXABLE,
FIXED_CREATE_DATA_ERROR,
FIXED_CREATE_SUCCESS,
FIXED_EDIT_MISSING_ARGS,
FIXED_EDIT_INVALID_ID,
FIXED_EDIT_INVALID_PROPERTY,
FIXED_EDIT_INVALID_COORDS,
FIXED_EDIT_OUT_OF_RANGE,
FIXED_EDIT_LOOKING_TOO_FAR,
FIXED_EDIT_EFFECT_INVALID,
FIXED_EDIT_EFFECT_NO_PERMISSION,
FIXED_EDIT_STYLE_INVALID,
FIXED_EDIT_STYLE_NO_PERMISSION,
FIXED_EDIT_STYLE_NON_FIXABLE,
FIXED_EDIT_DATA_ERROR,
FIXED_EDIT_DATA_NONE,
FIXED_EDIT_SUCCESS,
FIXED_REMOVE_INVALID,
FIXED_REMOVE_NO_ARGS,
FIXED_REMOVE_ARGS_INVALID,
FIXED_REMOVE_SUCCESS,
FIXED_LIST_NONE,
FIXED_LIST_SUCCESS,
FIXED_INFO_INVALID,
FIXED_INFO_NO_ARGS,
FIXED_INFO_INVALID_ARGS,
FIXED_INFO_SUCCESS,
FIXED_CLEAR_NO_PERMISSION,
FIXED_CLEAR_NO_ARGS,
FIXED_CLEAR_INVALID_ARGS,
FIXED_CLEAR_SUCCESS,
FIXED_NO_PERMISSION,
FIXED_MAX_REACHED,
FIXED_INVALID_COMMAND,
// GUI
GUI_DISABLED,
GUI_COLOR_ICON_NAME,
GUI_COLOR_INFO,
GUI_COLOR_SUBTEXT,
GUI_COLOR_UNAVAILABLE,
GUI_COMMANDS_INFO,
GUI_BACK_BUTTON,
GUI_CLICK_TO_LOAD,
GUI_SHIFT_CLICK_TO_DELETE,
GUI_PARTICLE_INFO,
GUI_PLAYERPARTICLES,
GUI_ACTIVE_PARTICLES,
GUI_SAVED_GROUPS,
GUI_FIXED_EFFECTS,
GUI_MANAGE_YOUR_PARTICLES,
GUI_MANAGE_YOUR_PARTICLES_DESCRIPTION,
GUI_MANAGE_YOUR_GROUPS,
GUI_MANAGE_YOUR_GROUPS_DESCRIPTION,
GUI_LOAD_A_PRESET_GROUP,
GUI_LOAD_A_PRESET_GROUP_DESCRIPTION,
GUI_SAVE_GROUP,
GUI_SAVE_GROUP_DESCRIPTION,
GUI_SAVE_GROUP_DESCRIPTION_2,
GUI_RESET_PARTICLES,
GUI_RESET_PARTICLES_DESCRIPTION,
GUI_PARTICLE_NAME,
GUI_CLICK_TO_EDIT_PARTICLE,
GUI_EDITING_PARTICLE,
GUI_EDIT_EFFECT,
GUI_EDIT_EFFECT_DESCRIPTION,
GUI_EDIT_STYLE,
GUI_EDIT_STYLE_DESCRIPTION,
GUI_EDIT_DATA,
GUI_EDIT_DATA_DESCRIPTION,
GUI_EDIT_DATA_UNAVAILABLE,
GUI_DATA_NONE,
GUI_CREATE_PARTICLE,
GUI_CREATE_PARTICLE_DESCRIPTION,
GUI_CREATE_PARTICLE_UNAVAILABLE,
GUI_SELECT_EFFECT,
GUI_SELECT_EFFECT_DESCRIPTION,
GUI_SELECT_STYLE,
GUI_SELECT_STYLE_DESCRIPTION,
GUI_SELECT_DATA,
GUI_SELECT_DATA_DESCRIPTION,
GUI_SELECT_DATA_NOTE,
GUI_SELECT_DATA_RANDOMIZE_ITEMS,
GUI_SELECT_DATA_RANDOMIZE_ITEMS_DESCRIPTION,
GUI_SELECT_DATA_RANDOMIZE_BLOCKS,
GUI_SELECT_DATA_RANDOMIZE_BLOCKS_DESCRIPTION,
GUI_EDIT_DATA_COLOR_RED,
GUI_EDIT_DATA_COLOR_ORANGE,
GUI_EDIT_DATA_COLOR_YELLOW,
GUI_EDIT_DATA_COLOR_LIME_GREEN,
GUI_EDIT_DATA_COLOR_GREEN,
GUI_EDIT_DATA_COLOR_BLUE,
GUI_EDIT_DATA_COLOR_CYAN,
GUI_EDIT_DATA_COLOR_LIGHT_BLUE,
GUI_EDIT_DATA_COLOR_PURPLE,
GUI_EDIT_DATA_COLOR_MAGENTA,
GUI_EDIT_DATA_COLOR_PINK,
GUI_EDIT_DATA_COLOR_BROWN,
GUI_EDIT_DATA_COLOR_BLACK,
GUI_EDIT_DATA_COLOR_GRAY,
GUI_EDIT_DATA_COLOR_LIGHT_GRAY,
GUI_EDIT_DATA_COLOR_WHITE;
// @formatter:on
private String message;
/**
* Gets the name of the message in the config
*
* @return The location in the config that this message is located
*/
private String getConfigName() {
return this.name().toLowerCase().replaceAll("_", "-");
}
/**
* Sets the message from the lang file
*
* @param langFile The lang file to pull the message from
*/
private void setMessage(YamlConfiguration langFile) {
String fileLocation = this.getConfigName();
String langMessage = langFile.getString(fileLocation);
if (langMessage == null) {
langMessage = "&cMissing message in " + langFileName + ": " + fileLocation + ". Contact a server administrator.";
PlayerParticles.getPlugin().getLogger().warning("Missing message in " + langFileName + ": " + fileLocation);
}
this.message = parseColors(langMessage);
}
/**
* Gets the message this enum represents
*
* @param replacements The replacements for the message
* @return The message with the replacements applied
*/
private String get(Object... replacements) {
return new MessageFormat(this.message).format(replacements);
}
}
/**
* The current lang file name
*/
private static String langFileName;
private LangManager() {
}
/**
* Used to set up the LangManager
* This should only get called once by the PlayerParticles class, however
* calling it multiple times wont affect anything negatively
*
* @param resetLangFile If the default.lang file should be updated to the latest version
*/
public static void reload(boolean resetLangFile) {
YamlConfiguration lang = configureLangFile(resetLangFile);
for (Lang messageType : Lang.values())
messageType.setMessage(lang);
}
/**
* Loads the target .lang file as defined in the config and grabs its YamlConfiguration
* If it doesn't exist, default to default.lang
* If default.lang doesn't exist, copy the file from this .jar to the target directory
*
* @param resetLangFile If the default.lang file should be updated to the latest version
* @return The YamlConfiguration of the target .lang file
*/
private static YamlConfiguration configureLangFile(boolean resetLangFile) {
File pluginDataFolder = PlayerParticles.getPlugin().getDataFolder();
langFileName = PSetting.LANG_FILE.getString();
File targetLangFile = new File(pluginDataFolder.getAbsolutePath() + "/lang/" + langFileName);
if (resetLangFile) {
File defaultLangFile = new File(pluginDataFolder.getAbsolutePath() + "/lang/default.lang");
if (defaultLangFile.exists()) {
defaultLangFile.delete();
PlayerParticles.getPlugin().getLogger().warning("default.lang has been reset!");
}
}
if (!targetLangFile.exists()) { // Target .lang file didn't exist, default to default.lang
if (!langFileName.equals("default.lang")) {
PlayerParticles.getPlugin().getLogger().warning("Couldn't find lang file '" + langFileName + "', defaulting to default.lang");
}
langFileName = "default.lang";
targetLangFile = new File(pluginDataFolder.getAbsolutePath() + "/lang/" + langFileName);
if (!targetLangFile.exists()) { // default.lang didn't exist, create it
try (InputStream stream = PlayerParticles.getPlugin().getResource("lang/default.lang")) {
targetLangFile.getParentFile().mkdir(); // Make sure the directory always exists
Files.copy(stream, Paths.get(targetLangFile.getAbsolutePath()));
return YamlConfiguration.loadConfiguration(targetLangFile);
} catch (IOException ex) {
ex.printStackTrace();
PlayerParticles.getPlugin().getLogger().severe("Unable to write default.lang to disk! You and your players will be seeing lots of error messages!");
return null;
}
}
}
return YamlConfiguration.loadConfiguration(targetLangFile);
}
/**
* Gets a formatted and replaced message
*
* @param messageType The message type to get
* @param replacements The replacements fot the message
* @return The Lang in text form with its replacements applied
*/
public static String getText(Lang messageType, Object... replacements) {
return messageType.get(replacements);
}
/**
* Sends a message to the given player
*
* @param player The player to send the message to
* @param messageType The message to send to the player
* @param replacements The replacements for the message
*/
public static void sendMessage(Player player, Lang messageType, Object... replacements) {
if (!PSetting.MESSAGES_ENABLED.getBoolean()) return;
String message = messageType.get(replacements);
if (message.length() == 0) return;
if (PSetting.USE_MESSAGE_PREFIX.getBoolean()) {
message = parseColors(PSetting.MESSAGE_PREFIX.getString()) + " " + message;
}
if (message.trim().equals("")) return;
player.sendMessage(message);
}
/**
* Sends a message to the given PPlayer
*
* @param pplayer The player to send the message to
* @param messageType The message to send to the player
* @param replacements The replacements for the message
*/
public static void sendMessage(PPlayer pplayer, Lang messageType, Object... replacements) {
sendMessage(pplayer.getPlayer(), messageType, replacements);
}
/**
* Sends a custom message to a player
* Used in cases of string building
*
* @param player The player to send the message to
* @param message The message to send to the player
*/
public static void sendCustomMessage(Player player, String message) {
if (!PSetting.MESSAGES_ENABLED.getBoolean()) return;
if (message.trim().length() == 0) return;
if (PSetting.USE_MESSAGE_PREFIX.getBoolean()) {
message = parseColors(PSetting.MESSAGE_PREFIX.getString()) + " " + message;
}
player.sendMessage(message);
}
/**
* Sends a custom message to a PPlayer
* Used in cases of string building
*
* @param pplayer The player to send the message to
* @param message The message to send to the player
*/
public static void sendCustomMessage(PPlayer pplayer, String message) {
sendCustomMessage(pplayer.getPlayer(), message);
}
/**
* Translates all ampersand symbols into the Minecraft chat color symbol
*
* @param message The input string
* @return The output string, parsed
*/
public static String parseColors(String message) {
return ChatColor.translateAlternateColorCodes('&', message);
}
}

View file

@ -1,252 +0,0 @@
/**
* 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.manager;
import org.bukkit.ChatColor;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.entity.Player;
import com.esophose.playerparticles.PlayerParticles;
public class MessageManager {
/**
* Contains the location in the config of every chat message
*/
public static enum MessageType {
// Particles
NO_PERMISSION("message-no-permission"),
NO_PARTICLES("message-no-particles"),
NOW_USING("message-now-using"),
CLEARED_PARTICLES("message-cleared-particles"),
INVALID_TYPE("message-invalid-type"),
PARTICLE_USAGE("message-particle-usage"),
// Styles
NO_PERMISSION_STYLE("message-no-permission-style"),
NO_STYLES("message-no-styles"),
NOW_USING_STYLE("message-now-using-style"),
CLEARED_STYLE("message-cleared-style"),
INVALID_TYPE_STYLE("message-invalid-type-style"),
STYLE_USAGE("message-style-usage"),
// Data
DATA_USAGE("message-data-usage"),
NO_DATA_USAGE("message-no-data-usage"),
DATA_APPLIED("message-data-applied"),
DATA_INVALID_ARGUMENTS("message-data-invalid-arguments"),
DATA_MATERIAL_UNKNOWN("message-data-material-unknown"),
DATA_MATERIAL_MISMATCH("message-data-material-mismatch"),
NOTE_DATA_USAGE("message-note-data-usage"),
COLOR_DATA_USAGE("message-color-data-usage"),
ITEM_DATA_USAGE("message-item-data-usage"),
BLOCK_DATA_USAGE("message-block-data-usage"),
// Fixed Effects
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"),
FIXED_COMMAND_DESC_CLEAR("message-fixed-command-desc-clear"),
CREATE_FIXED_MISSING_ARGS("message-create-fixed-missing-args"),
CREATE_FIXED_INVALID_COORDS("message-create-fixed-invalid-coords"),
CREATE_FIXED_OUT_OF_RANGE("message-create-fixed-out-of-range"),
CREATE_FIXED_INVALID_EFFECT("message-create-fixed-invalid-effect"),
CREATE_FIXED_NO_PERMISSION_EFFECT("message-create-fixed-no-permission-effect"),
CREATE_FIXED_INVALID_STYLE("message-create-fixed-invalid-style"),
CREATE_FIXED_NO_PERMISSION_STYLE("message-create-fixed-no-permission-style"),
CREATE_FIXED_NON_FIXABLE_STYLE("message-create-fixed-non-fixable-style"),
CREATE_FIXED_DATA_ERROR("message-create-fixed-data-error"),
CREATE_FIXED_SUCCESS("message-create-fixed-success"),
REMOVE_FIXED_NONEXISTANT("message-remove-fixed-nonexistant"),
REMOVE_FIXED_NO_ARGS("message-remove-fixed-no-args"),
REMOVE_FIXED_INVALID_ARGS("message-remove-fixed-invalid-args"),
REMOVE_FIXED_SUCCESS("message-remove-fixed-success"),
LIST_FIXED_SUCCESS("message-list-fixed-success"),
LIST_FIXED_NONE("message-list-fixed-none"),
INFO_FIXED_NONEXISTANT("message-info-fixed-nonexistant"),
INFO_FIXED_NO_ARGS("message-info-fixed-no-args"),
INFO_FIXED_INVALID_ARGS("message-info-fixed-invalid-args"),
INFO_FIXED_INFO("message-info-fixed-info"),
CLEAR_FIXED_NO_PERMISSION("message-clear-no-permission"),
CLEAR_FIXED_NO_ARGS("message-clear-no-args"),
CLEAR_FIXED_INVALID_ARGS("message-clear-invalid-args"),
CLEAR_FIXED_SUCCESS("message-clear-success"),
NO_PERMISSION_FIXED("message-no-permission-fixed"),
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"),
RESET("message-reset"),
// Other
INVALID_ARGUMENTS("message-invalid-arguments"),
AVAILABLE_COMMANDS("message-available-commands"),
DISABLED_WORLDS_NONE("message-disabled-worlds-none"),
DISABLED_WORLDS("message-disabled-worlds"),
COMMAND_USAGE("message-command-usage"),
EXECUTED_FOR_PLAYER("message-executed-for-player"),
FAILED_EXECUTE_NOT_FOUND("message-failed-execute-not-found"),
FAILED_EXECUTE_NO_PERMISSION("message-failed-execute-no-permission");
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) {
String messageFromConfig = config.getString(configLocation);
if (messageFromConfig == null) {
messageFromConfig = "&cMissing message in config.yml. Contact a server administrator.";
PlayerParticles.getPlugin().getLogger().warning("Missing message in config.yml: " + this.configLocation);
}
this.message = parseColors(messageFromConfig);
}
/**
* Gets the message this enum represents
*
* @return The message
*/
public String getMessage() {
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);
}
}
/**
* Stores the main config for quick access
*/
private static FileConfiguration config;
/**
* Stores if messages and their prefixes should be displayed
*/
private static boolean messagesEnabled, prefixEnabled;
/**
* The prefix to place before all sent messages contained in the config
*/
private static String messagePrefix;
/**
* Used to set up the MessageManager
* This should only get called once by the PlayerParticles class, however
* calling it multiple times wont affect anything negatively
*/
public static void setup() {
config = PlayerParticles.getPlugin().getConfig();
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);
}
}
/**
* Sends a message to the given player
*
* @param player The player to send the message to
* @param messageType The message to send to the player
*/
public static void sendMessage(Player player, MessageType messageType) {
if (!messagesEnabled) return;
String message = messageType.getMessage();
if (message.length() == 0) return;
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
*/
public static void sendMessage(Player player, MessageType messageType, String typeReplacement) {
if (!messagesEnabled) return;
String message = messageType.getMessageReplaced(typeReplacement);
if (message.trim().length() == 0) return;
if (prefixEnabled) {
message = messagePrefix + " " + message;
}
player.sendMessage(message);
}
/**
* Sends a custom message
* Used in cases of string building
*
* @param player The player to send the message to
* @param message The message to send to the player
*/
public static void sendCustomMessage(Player player, String message) {
if (!messagesEnabled) return;
if (message.trim().length() == 0) return;
if (prefixEnabled) {
message = messagePrefix + " " + message;
}
player.sendMessage(message);
}
/**
* Translates all ampersand symbols into the Minecraft chat color symbol
*
* @param message The input string
* @return The output string, parsed
*/
public static String parseColors(String message) {
return ChatColor.translateAlternateColorCodes('&', message);
}
}

View file

@ -1,998 +0,0 @@
/**
* 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.manager;
import java.io.File;
import java.io.IOException;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.HashSet;
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 org.bukkit.scheduler.BukkitRunnable;
import com.esophose.playerparticles.PPlayer;
import com.esophose.playerparticles.PlayerParticles;
import com.esophose.playerparticles.particles.FixedParticleEffect;
import com.esophose.playerparticles.particles.ParticleEffect;
import com.esophose.playerparticles.particles.ParticleEffect.BlockData;
import com.esophose.playerparticles.particles.ParticleEffect.ItemData;
import com.esophose.playerparticles.particles.ParticleEffect.NoteColor;
import com.esophose.playerparticles.particles.ParticleEffect.OrdinaryColor;
import com.esophose.playerparticles.styles.api.ParticleStyle;
import com.esophose.playerparticles.styles.api.ParticleStyleManager;
import com.esophose.playerparticles.util.ParticleUtils;
public class PPlayerDataManager {
/**
* The instance of the ConfigManager used for effect data
*/
private static PPlayerDataManager instance = new PPlayerDataManager("pplayerData");
/**
* The file the data is located in for the instance
*/
private File playerDataYamlFile;
/**
* The configuration used to edit the .yaml file
*/
private FileConfiguration playerDataYaml;
/**
* The disabled worlds cached for quick access
*/
private List<String> disabledWorlds = null;
/**
* The max number of fixed effects a player can have, defined in the config
*/
private int maxFixedEffects = -1;
/**
* The max distance a fixed effect can be created relative to the player
*/
private int maxFixedEffectCreationDistance = -1;
/**
* @return The instance of the config for effects
*/
public static PPlayerDataManager getInstance() {
return instance;
}
/**
* @param fileName The name of the file
*/
private PPlayerDataManager(String fileName) {
if (!PlayerParticles.useMySQL) { // Don't bother creating the playerData.yml file if we aren't going to use it
if (!PlayerParticles.getPlugin().getDataFolder().exists()) PlayerParticles.getPlugin().getDataFolder().mkdir();
playerDataYamlFile = new File(PlayerParticles.getPlugin().getDataFolder(), fileName + ".yml");
if (!playerDataYamlFile.exists()) {
try {
playerDataYamlFile.createNewFile();
} catch (Exception e) {
e.printStackTrace();
}
}
playerDataYaml = YamlConfiguration.loadConfiguration(playerDataYamlFile);
}
}
/**
* Saves the playerData.yml file to disk
*/
private void save() {
try {
playerDataYaml.save(playerDataYamlFile);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* Gets a PPlayer from cache
* This method should be used over the other one unless you absolutely need the PPlayer and you don't care about waiting
* You should always check for a null result when using this method
*
* @param playerUUID The PPlayer to get
* @return The PPlayer from cache
*/
public PPlayer getPPlayer(UUID playerUUID) {
for (PPlayer pp : ParticleManager.particlePlayers)
if (pp.getUniqueId() == playerUUID)
return pp;
return null;
}
/**
* Gets a player from the save data, creates one if it doesn't exist and caches it
*
* @param playerUUID The pplayer to get
* @param callback The callback to execute with the found pplayer, or a newly generated one
*/
public void getPPlayer(UUID playerUUID, ConfigurationCallback<PPlayer> callback) {
// Try to get them from cache first
PPlayer fromCache = getPPlayer(playerUUID);
if (fromCache != null) {
callback.execute(fromCache);
return;
}
// Either get an existing one from the database, or create a new one
buildPPlayer(playerUUID, true, (pplayer) -> {
ParticleManager.particlePlayers.add(pplayer);
callback.execute(pplayer);
});
}
/**
* Gets a PPlayer matching the UUID given
* If createIfNotFound is true, one will be created if it doesn't exist
*
* @param playerUUID The UUID to match the PPlayer to
* @param createIfNotFound If true, creates a new PPlayer if the requested one doesn't exist
* @param callback The callback to execute with the built PPlayer
*/
private void buildPPlayer(UUID playerUUID, boolean createIfNotFound, ConfigurationCallback<PPlayer> callback) {
if (!PlayerParticles.useMySQL) {
if (playerDataYaml.contains(playerUUID.toString())) {
ConfigurationSection section = playerDataYaml.getConfigurationSection(playerUUID.toString());
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");
ParticleEffect particleEffect = ParticleEffect.fromName(effectSection.getString("name"));
ParticleStyle particleStyle = ParticleStyleManager.styleFromString(styleSection.getString("name"));
ItemData particleItemData = new ItemData(Material.matchMaterial(itemDataSection.getString("material")));
BlockData particleBlockData = new BlockData(Material.matchMaterial(blockDataSection.getString("material")));
OrdinaryColor particleColorData = new OrdinaryColor(colorDataSection.getInt("r"), colorDataSection.getInt("g"), colorDataSection.getInt("b"));
NoteColor particleNoteColorData = new NoteColor(noteColorDataSection.getInt("note"));
callback.execute(new PPlayer(playerUUID, particleEffect, particleStyle, particleItemData, particleBlockData, particleColorData, particleNoteColorData));
return;
}
if (createIfNotFound) {
// Didn't find an existing PPlayer, create and return a new one
PPlayer pplayer = PPlayer.getNewPPlayer(playerUUID);
saveNewPPlayer(pplayer);
callback.execute(pplayer);
}
} else {
async(() -> {
String id = playerUUID.toString(); // @formatter:off
PlayerParticles.mySQL.connect((connection) -> {
String query = "SELECT * FROM pp_users u " +
"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 + "'";
try (Statement statement = connection.createStatement();
ResultSet res = statement.executeQuery(query)) {
if (res.next()) {
ParticleEffect particleEffect = ParticleEffect.fromName(res.getString("u.effect"));
ParticleStyle particleStyle = ParticleStyleManager.styleFromString(res.getString("u.style"));
ItemData particleItemData = new ItemData(Material.matchMaterial(res.getString("i.material")));
BlockData particleBlockData = new BlockData(Material.matchMaterial(res.getString("b.material")));
OrdinaryColor particleColorData = new OrdinaryColor(res.getInt("c.r"), res.getInt("c.g"), res.getInt("c.b"));
NoteColor particleNoteColorData = new NoteColor(res.getByte("n.note"));
sync(() -> callback.execute(new PPlayer(playerUUID, particleEffect, particleStyle, particleItemData, particleBlockData, particleColorData, particleNoteColorData)));
return;
}
if (createIfNotFound) { // Didn't find an existing PPlayer, create and return a new one
PPlayer pplayer = PPlayer.getNewPPlayer(playerUUID);
saveNewPPlayer(pplayer);
sync(() -> callback.execute(pplayer));
}
}
});
});
}
}
/**
* Saves a new PPlayer to the database or the file
*
* @param pplayer The PPlayer to save
*/
public void saveNewPPlayer(PPlayer pplayer) {
if (!PlayerParticles.useMySQL) {
if (!playerDataYaml.isConfigurationSection(pplayer.getUniqueId().toString())) {
String id = pplayer.getUniqueId().toString();
playerDataYaml.createSection(id);
playerDataYaml.createSection(id + ".effect");
playerDataYaml.createSection(id + ".style");
playerDataYaml.createSection(id + ".itemData");
playerDataYaml.createSection(id + ".blockData");
playerDataYaml.createSection(id + ".colorData");
playerDataYaml.createSection(id + ".noteColorData");
}
ConfigurationSection section = playerDataYaml.getConfigurationSection(pplayer.getUniqueId().toString());
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");
effectSection.set("name", pplayer.getParticleEffect().getName());
styleSection.set("name", pplayer.getParticleStyle().getName());
itemDataSection.set("material", pplayer.getItemData().getMaterial().name());
blockDataSection.set("material", pplayer.getBlockData().getMaterial().name());
colorDataSection.set("r", pplayer.getColorData().getRed());
colorDataSection.set("g", pplayer.getColorData().getGreen());
colorDataSection.set("b", pplayer.getColorData().getBlue());
noteColorDataSection.set("note", (byte) (pplayer.getNoteColorData().getValueX() * 24));
save();
} else {
async(() -> {
PlayerParticles.mySQL.connect((connection) -> {
try (Statement statement = connection.createStatement();
ResultSet res = statement.executeQuery("SELECT * FROM pp_users WHERE player_uuid = '" + pplayer.getUniqueId() + "'")) {
if (!res.next()) {
PlayerParticles.mySQL.updateSQL("INSERT INTO pp_users (player_uuid, effect, style) VALUES (" +
"'" + pplayer.getUniqueId().toString() + "', " +
"'" + pplayer.getParticleEffect().getName() + "', " +
"'" + pplayer.getParticleStyle().getName() + "'" +
"); " +
"INSERT INTO pp_data_item (uuid, material) VALUES (" +
"'" + pplayer.getUniqueId().toString() + "', " +
"'" + pplayer.getItemData().getMaterial().name() + "'" +
"); " +
"INSERT INTO pp_data_block (uuid, material) VALUES (" +
"'" + pplayer.getUniqueId().toString() + "', " +
"'" + pplayer.getBlockData().getMaterial().name() + "'" +
"); " +
"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 (uuid, note) VALUES (" +
"'" + pplayer.getUniqueId().toString() + "', " +
(byte) (pplayer.getNoteColorData().getValueX() * 24) +
");"
);
} else {
throw new RuntimeException("The user " + pplayer.getUniqueId() + " is already in the database. They can not be added.");
}
}
});
});
}
ParticleManager.updateIfContains(pplayer); // Update the player in case this is a /pp reset
}
/**
* Loads a PPlayer and caches it
*
* @param playerUUID The pplayer to load
*/
public void loadPPlayer(UUID playerUUID) {
for (PPlayer pplayer : ParticleManager.particlePlayers)
if (pplayer.getUniqueId() == playerUUID)
return;
buildPPlayer(playerUUID, false, (pplayer) -> {
ParticleManager.particlePlayers.add(pplayer);
});
}
/**
* Resets all saved information about a PPlayer
* This should be made into a single batch query in the future
*
* @param playerUUID The pplayer to reset
*/
public void resetPPlayer(UUID playerUUID) {
PPlayer pplayer = PPlayer.getNewPPlayer(playerUUID);
savePPlayer(playerUUID, pplayer.getParticleEffect());
savePPlayer(playerUUID, pplayer.getParticleStyle());
savePPlayer(playerUUID, pplayer.getItemData());
savePPlayer(playerUUID, pplayer.getBlockData());
savePPlayer(playerUUID, pplayer.getColorData());
savePPlayer(playerUUID, pplayer.getNoteColorData());
}
/**
* Saves the effect to the player's save file or database entry
*
* @param playerUUID The UUID of the player
* @param particleEffect The effect that is being saved
*/
public void savePPlayer(UUID playerUUID, ParticleEffect particleEffect) {
getPPlayer(playerUUID, (pplayer) -> {
if (!PlayerParticles.useMySQL) {
ConfigurationSection section = playerDataYaml.getConfigurationSection(playerUUID.toString() + ".effect");
section.set("name", particleEffect.getName());
save();
} else {
async(() -> {
try {
PlayerParticles.mySQL.updateSQL("UPDATE pp_users SET effect = '" + particleEffect.getName() + "' WHERE player_uuid = '" + playerUUID + "';");
} catch (SQLException e) {
e.printStackTrace();
}
});
}
pplayer.setParticleEffect(particleEffect);
});
}
/**
* Saves the style to the player's save file or database entry
*
* @param playerUUID The UUID of the player
* @param particleStyle The style that is being saved
*/
public void savePPlayer(UUID playerUUID, ParticleStyle particleStyle) {
getPPlayer(playerUUID, (pplayer) -> {
if (!PlayerParticles.useMySQL) {
ConfigurationSection section = playerDataYaml.getConfigurationSection(playerUUID.toString() + ".style");
section.set("name", particleStyle.getName());
save();
} else {
async(() -> {
try {
PlayerParticles.mySQL.updateSQL("UPDATE pp_users SET style = '" + particleStyle.getName() + "' WHERE player_uuid = '" + playerUUID + "';");
} catch (SQLException e) {
e.printStackTrace();
}
});
}
pplayer.setParticleStyle(particleStyle);
});
}
/**
* Saves the item data to the player's save file or database entry
*
* @param playerUUID The UUID of the player
* @param particleItemData The data that is being saved
*/
public void savePPlayer(UUID playerUUID, ItemData particleItemData) {
getPPlayer(playerUUID, (pplayer) -> {
if (!PlayerParticles.useMySQL) {
ConfigurationSection section = playerDataYaml.getConfigurationSection(playerUUID.toString() + ".itemData");
section.set("material", particleItemData.getMaterial().name());
save();
} else {
async(() -> {
try {
PlayerParticles.mySQL.updateSQL("UPDATE pp_data_item SET material = '" + particleItemData.getMaterial().name() + "' WHERE uuid = '" + playerUUID + "';");
} catch (SQLException e) {
e.printStackTrace();
}
});
}
pplayer.setItemData(particleItemData);
});
}
/**
* Saves the block data to the player's save file or database entry
*
* @param playerUUID The UUID of the player
* @param particleBlockData The data that is being saved
*/
public void savePPlayer(UUID playerUUID, BlockData particleBlockData) {
getPPlayer(playerUUID, (pplayer) -> {
if (!PlayerParticles.useMySQL) {
ConfigurationSection section = playerDataYaml.getConfigurationSection(playerUUID.toString() + ".blockData");
section.set("material", particleBlockData.getMaterial().name());
save();
} else {
async(() -> {
try {
PlayerParticles.mySQL.updateSQL("UPDATE pp_data_block SET material = '" + particleBlockData.getMaterial().name() + "' WHERE uuid = '" + playerUUID + "';");
} catch (SQLException e) {
e.printStackTrace();
}
});
}
pplayer.setBlockData(particleBlockData);
});
}
/**
* Saves the color data to the player's save file or database entry
*
* @param playerUUID The UUID of the player
* @param particleColorData The data that is being saved
*/
public void savePPlayer(UUID playerUUID, OrdinaryColor particleColorData) {
getPPlayer(playerUUID, (pplayer) -> {
if (!PlayerParticles.useMySQL) {
ConfigurationSection section = playerDataYaml.getConfigurationSection(playerUUID.toString() + ".colorData");
section.set("r", particleColorData.getRed());
section.set("g", particleColorData.getGreen());
section.set("b", particleColorData.getBlue());
save();
} else {
async(() -> {
try {
PlayerParticles.mySQL.updateSQL("UPDATE pp_data_color SET r = " + particleColorData.getRed() + ", g = " + particleColorData.getGreen() + ", b = " + particleColorData.getBlue() + " WHERE uuid = '" + playerUUID + "';");
} catch (SQLException e) {
e.printStackTrace();
}
});
}
pplayer.setColorData(particleColorData);
});
}
/**
* Saves the note color data to the player's save file or database entry
*
* @param playerUUID The UUID of the player
* @param particleNoteColorData The data that is being saved
*/
public void savePPlayer(UUID playerUUID, NoteColor particleNoteColorData) {
getPPlayer(playerUUID, (pplayer) -> {
if (!PlayerParticles.useMySQL) {
ConfigurationSection section = playerDataYaml.getConfigurationSection(playerUUID.toString() + ".noteColorData");
section.set("note", (byte) (particleNoteColorData.getValueX() * 24));
save();
} else {
async(() -> {
try {
PlayerParticles.mySQL.updateSQL("UPDATE pp_data_note SET note = " + (byte) (particleNoteColorData.getValueX() * 24) + " WHERE uuid = '" + playerUUID + "';");
} catch (SQLException e) {
e.printStackTrace();
}
});
}
pplayer.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 (!playerDataYaml.isConfigurationSection(fixedEffect.getOwnerUniqueId().toString() + ".fixedEffect." + fixedEffect.getId())) {
ConfigurationSection baseSection = playerDataYaml.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 {
return;
}
ConfigurationSection section = playerDataYaml.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());
blockDataSection.set("material", fixedEffect.getBlockData().getMaterial().name());
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();
ParticleManager.addFixedEffect(fixedEffect);
} else {
async(() -> {
PlayerParticles.mySQL.connect((connection) -> {
try (Statement statement = connection.createStatement();
ResultSet res = statement.executeQuery("SELECT * FROM pp_fixed WHERE player_uuid = '" + fixedEffect.getOwnerUniqueId() + "' AND id = " + fixedEffect.getId())) {
if (res.next()) {
return;
}
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) VALUES (" +
"'" + fixedEffectUUID + "', " +
"'" + fixedEffect.getItemData().getMaterial().name() + "'" +
"); " +
"INSERT INTO pp_data_block (uuid, material) VALUES (" +
"'" + fixedEffectUUID + "', " +
"'" + fixedEffect.getBlockData().getMaterial().name() + "'" +
"); " +
"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) +
");"
);
sync(() -> 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
* @param callback The callback to execute with if the fixed effect was removed or not
*/
public void removeFixedEffect(UUID playerUUID, int id, ConfigurationCallback<Boolean> callback) {
if (!PlayerParticles.useMySQL) {
if (!playerDataYaml.isConfigurationSection(playerUUID.toString() + ".fixedEffect." + id)) {
callback.execute(false);
return;
}
playerDataYaml.set(playerUUID.toString() + ".fixedEffect." + id, null);
save();
ParticleManager.removeFixedEffectForPlayer(playerUUID, id);
callback.execute(true);
} else {
async(() -> {
PlayerParticles.mySQL.connect((connection) -> {
try (Statement statement = connection.createStatement();
ResultSet res = statement.executeQuery("SELECT uuid FROM pp_fixed WHERE player_uuid = '" + playerUUID.toString() + "' AND id = " + id)) {
if (!res.next()) {
callback.execute(false);
return;
}
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 + "';"
);
sync(() -> {
ParticleManager.removeFixedEffectForPlayer(playerUUID, id);
callback.execute(true);
});
}
});
});
}
}
/**
* 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) {
playerDataYaml.set(playerUUID.toString() + ".fixedEffect", null);
save();
} else {
async(() -> {
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 (SQLException e) {
e.printStackTrace();
}
});
}
ParticleManager.removeAllFixedEffectsForPlayer(playerUUID);
}
/**
* Gets a list of all saved fixed particle effects
*
* @param callback The callback to execute with a list of all saved fixed particle effects
*/
public void getAllFixedEffects(ConfigurationCallback<List<FixedParticleEffect>> callback) {
if (!PlayerParticles.useMySQL) {
List<FixedParticleEffect> fixedEffects = new ArrayList<FixedParticleEffect>();
Set<String> playerKeys = playerDataYaml.getKeys(false);
for (String playerKey : playerKeys) {
if (playerDataYaml.isConfigurationSection(playerKey + ".fixedEffect")) {
Set<String> fixedEffectKeys = playerDataYaml.getConfigurationSection(playerKey + ".fixedEffect").getKeys(false);
for (String fixedEffectKey : fixedEffectKeys) {
ConfigurationSection section = playerDataYaml.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")));
BlockData particleBlockData = new BlockData(Material.matchMaterial(blockDataSection.getString("material")));
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));
}
}
}
callback.execute(fixedEffects);
} else { // @formatter:off
async(() -> {
PlayerParticles.mySQL.connect((connection) -> {
String query = "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";
try (Statement statement = connection.createStatement();
ResultSet res = statement.executeQuery(query)) {
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.effectFromString(res.getString("f.effect"));
ParticleStyle particleStyle = ParticleStyleManager.styleFromString(res.getString("f.style"));
ItemData particleItemData = new ItemData(Material.matchMaterial(res.getString("i.material")));
BlockData particleBlockData = new BlockData(Material.matchMaterial(res.getString("b.material")));
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));
}
sync(() -> callback.execute(fixedEffects));
}
});
});
}
}
/**
* Gets a fixed effect for a pplayer by its id
*
* @param pplayerUUID The player who owns the effect
* @param id The id for the effect to get
* @param callback The callback to execute with the effect, if one exists
*/
public void getFixedEffectForPlayerById(UUID pplayerUUID, int id, ConfigurationCallback<FixedParticleEffect> callback) {
if (!PlayerParticles.useMySQL) {
if (playerDataYaml.isConfigurationSection(pplayerUUID.toString() + ".fixedEffect." + id)) {
ConfigurationSection section = playerDataYaml.getConfigurationSection(pplayerUUID + ".fixedEffect." + id);
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");
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")));
BlockData particleBlockData = new BlockData(Material.matchMaterial(blockDataSection.getString("material")));
OrdinaryColor particleColorData = new OrdinaryColor(colorDataSection.getInt("r"), colorDataSection.getInt("g"), colorDataSection.getInt("b"));
NoteColor particleNoteColorData = new NoteColor(noteColorDataSection.getInt("note"));
callback.execute(new FixedParticleEffect(pplayerUUID, id, worldName, xPos, yPos, zPos, particleEffect, particleStyle, particleItemData, particleBlockData, particleColorData, particleNoteColorData));
}
} else {
async(() -> {
PlayerParticles.mySQL.connect((connection) -> { // @formatter:off
String query = "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 " +
"WHERE f.player_uuid = '" + pplayerUUID.toString() + "' AND f.id = '" + id + "'"; // @formatter:on
try (Statement statement = connection.createStatement();
ResultSet res = statement.executeQuery(query)) {
if (res.next()) {
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.effectFromString(res.getString("f.effect"));
ParticleStyle particleStyle = ParticleStyleManager.styleFromString(res.getString("f.style"));
ItemData particleItemData = new ItemData(Material.matchMaterial(res.getString("i.material")));
BlockData particleBlockData = new BlockData(Material.matchMaterial(res.getString("b.material")));
OrdinaryColor particleColorData = new OrdinaryColor(res.getInt("c.r"), res.getInt("c.g"), res.getInt("c.b"));
NoteColor particleNoteColorData = new NoteColor(res.getByte("n.note"));
sync(() -> callback.execute(new FixedParticleEffect(pplayerUUID, id, worldName, xPos, yPos, zPos, particleEffect, particleStyle, particleItemData, particleBlockData, particleColorData, particleNoteColorData)));
}
}
});
});
}
}
/**
* Gets a list of all fixed effect ids for a player
*
* @param pplayerUUID The player
* @param callback The callback to execute with a list of all fixed effect ids for the given player
*/
public void getFixedEffectIdsForPlayer(UUID pplayerUUID, ConfigurationCallback<List<Integer>> callback) {
if (!PlayerParticles.useMySQL) {
List<Integer> ids = new ArrayList<Integer>();
if (playerDataYaml.isConfigurationSection(pplayerUUID.toString() + ".fixedEffect")) {
Set<String> keys = playerDataYaml.getConfigurationSection(pplayerUUID.toString() + ".fixedEffect").getKeys(false);
for (String key : keys) {
ids.add(Integer.parseInt(key));
}
}
callback.execute(ids);
} else {
async(() -> {
PlayerParticles.mySQL.connect((connection) -> {
try (Statement statement = connection.createStatement();
ResultSet res = statement.executeQuery("SELECT id FROM pp_fixed WHERE player_uuid = '" + pplayerUUID.toString() + "'")) {
List<Integer> ids = new ArrayList<Integer>();
while (res.next()) {
ids.add(res.getInt(1));
}
sync(() -> callback.execute(ids));
}
});
});
}
}
/**
* Checks if the given player has reached the max number of fixed effects
*
* @param pplayerUUID The player to check
* @param callback The callback to execute with if the player can create any more fixed effects
*/
public void hasPlayerReachedMaxFixedEffects(UUID pplayerUUID, ConfigurationCallback<Boolean> callback) {
if (maxFixedEffects == -1) { // Initialize on the fly
maxFixedEffects = PlayerParticles.getPlugin().getConfig().getInt("max-fixed-effects");
}
if (Bukkit.getPlayer(pplayerUUID).hasPermission("playerparticles.fixed.unlimited")) {
callback.execute(false);
return;
}
if (!PlayerParticles.useMySQL) {
if (playerDataYaml.isConfigurationSection(pplayerUUID.toString() + ".fixedEffect")) {
callback.execute(playerDataYaml.getConfigurationSection(pplayerUUID.toString() + ".fixedEffect").getKeys(false).size() >= maxFixedEffects);
} else callback.execute(false);
} else {
async(() -> {
PlayerParticles.mySQL.connect((connection) -> {
try (Statement statement = connection.createStatement();
ResultSet res = statement.executeQuery("SELECT COUNT(1) FROM pp_fixed WHERE player_uuid = '" + pplayerUUID.toString() + "'")) {
boolean hasReachedMax;
if (res.next())
hasReachedMax = res.getInt(1) >= maxFixedEffects;
else
hasReachedMax = false;
sync(() -> callback.execute(hasReachedMax));
}
});
});
}
}
/**
* Gets the next Id for a player's fixed effects
*
* @param pplayerUUID The player to get the Id for
* @param callback The callback to execute with the smallest available Id the player can use
*/
public void getNextFixedEffectId(UUID pplayerUUID, ConfigurationCallback<Integer> callback) {
if (!PlayerParticles.useMySQL) {
if (!playerDataYaml.isConfigurationSection(pplayerUUID.toString() + ".fixedEffect")) {
callback.execute(1);
return;
}
Set<String> idsSet = playerDataYaml.getConfigurationSection(pplayerUUID.toString() + ".fixedEffect").getKeys(false);
if (idsSet.isEmpty()) callback.execute(1);
int[] ids = new int[idsSet.size()];
int i = 0;
for (String key : idsSet)
ids[i++] = Integer.parseInt(key);
callback.execute(ParticleUtils.getSmallestPositiveInt(ids));
} else {
async(() -> {
PlayerParticles.mySQL.connect((connection) -> {
try (Statement statement = connection.createStatement();
ResultSet res = statement.executeQuery("SELECT id FROM pp_fixed WHERE player_uuid = '" + pplayerUUID.toString() + "'")) {
Set<String> idsSet = new HashSet<String>();
while (res.next())
idsSet.add(res.getInt(1) + "");
if (idsSet.isEmpty()) {
sync(() -> callback.execute(1));
return;
}
int[] ids = new int[idsSet.size()];
int i = 0;
for (String key : idsSet)
ids[i++] = Integer.parseInt(key);
sync(() -> callback.execute(ParticleUtils.getSmallestPositiveInt(ids)));
}
});
});
}
}
/**
* Gets the max distance a fixed effect can be created from the player
*
* @return The max distance a fixed effect can be created from the player
*/
public int getMaxFixedEffectCreationDistance() {
if (maxFixedEffectCreationDistance == -1) { // Initialize on the fly
maxFixedEffectCreationDistance = PlayerParticles.getPlugin().getConfig().getInt("max-fixed-effect-creation-distance");
}
return maxFixedEffectCreationDistance;
}
/**
* Checks if a world is disabled for particles to spawn in
*
* @param world The world name to check
* @return True if the world is disabled
*/
public boolean isWorldDisabled(String world) {
return getDisabledWorlds().contains(world);
}
/**
* Gets all the worlds that are disabled
*
* @return All world names that are disabled
*/
public List<String> getDisabledWorlds() {
if (disabledWorlds == null) { // Initialize on the fly
disabledWorlds = PlayerParticles.getPlugin().getConfig().getStringList("disabled-worlds");
}
return disabledWorlds;
}
/**
* Asynchronizes the callback with it's own thread
*
* @param asyncCallback The callback to run on a separate thread
*/
private void async(SyncInterface asyncCallback) {
new BukkitRunnable() {
public void run() {
asyncCallback.execute();
}
}.runTaskAsynchronously(PlayerParticles.getPlugin());
}
/**
* Synchronizes the callback with the main thread
*
* @param syncCallback The callback to run on the main thread
*/
private void sync(SyncInterface syncCallback) {
new BukkitRunnable() {
public void run() {
syncCallback.execute();
}
}.runTask(PlayerParticles.getPlugin());
}
/**
* Provides an easy way to run a section of code either synchronously or asynchronously using a callback
*/
private static interface SyncInterface {
public void execute();
}
/**
* Allows callbacks to be passed between configuration methods and executed for returning objects after database queries
*/
public static interface ConfigurationCallback<T> {
public void execute(T obj);
}
}

View file

@ -1,16 +1,9 @@
/**
* 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.manager;
import java.awt.Color;
import java.util.ArrayList;
import java.util.UUID;
import java.util.List;
import java.util.Random;
import org.bukkit.Bukkit;
import org.bukkit.GameMode;
@ -23,26 +16,21 @@ import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.scheduler.BukkitRunnable;
import com.esophose.playerparticles.PPlayer;
import com.esophose.playerparticles.particles.FixedParticleEffect;
import com.esophose.playerparticles.particles.PPlayer;
import com.esophose.playerparticles.particles.ParticleEffect;
import com.esophose.playerparticles.particles.ParticleEffect.NoteColor;
import com.esophose.playerparticles.particles.ParticleEffect.OrdinaryColor;
import com.esophose.playerparticles.particles.ParticleEffect.ParticleProperty;
import com.esophose.playerparticles.particles.ParticlePair;
import com.esophose.playerparticles.styles.api.PParticle;
import com.esophose.playerparticles.styles.api.ParticleStyleManager;
public class ParticleManager extends BukkitRunnable implements Listener {
/**
* The list containing all the player effect info
* The list containing all the loaded PPlayer info
*/
public static ArrayList<PPlayer> particlePlayers = new ArrayList<PPlayer>();
/**
* The list containing all the fixed effect info
*/
public static ArrayList<FixedParticleEffect> fixedParticleEffects = new ArrayList<FixedParticleEffect>();
public static List<PPlayer> particlePlayers = new ArrayList<PPlayer>();
/**
* Rainbow particle effect hue and note color used for rainbow colorable effects
@ -50,6 +38,7 @@ public class ParticleManager extends BukkitRunnable implements Listener {
*/
private static int hue = 0;
private static int note = 0;
private static final Random RANDOM = new Random();
/**
* Adds the player to the array when they join
@ -58,7 +47,7 @@ public class ParticleManager extends BukkitRunnable implements Listener {
*/
@EventHandler(priority = EventPriority.MONITOR)
public void onPlayerJoin(PlayerJoinEvent e) {
PPlayerDataManager.getInstance().loadPPlayer(e.getPlayer().getUniqueId());
DataManager.getPPlayer(e.getPlayer().getUniqueId(), (pplayer) -> { }); // Loads the PPlayer from the database
}
/**
@ -68,90 +57,31 @@ public class ParticleManager extends BukkitRunnable implements Listener {
*/
@EventHandler(priority = EventPriority.MONITOR)
public void onPlayerQuit(PlayerQuitEvent e) {
PPlayer pplayer = PPlayerDataManager.getInstance().getPPlayer(e.getPlayer().getUniqueId());
if (pplayer != null)
particlePlayers.remove(pplayer);
PPlayer pplayer = DataManager.getPPlayer(e.getPlayer().getUniqueId());
if (pplayer != null && pplayer.getFixedEffectIds().isEmpty()) particlePlayers.remove(pplayer); // Unload the PPlayer if they don't have any fixed effects
}
/**
* Adds all fixed effects from the config
*/
public static void addAllFixedEffects() {
PPlayerDataManager.getInstance().getAllFixedEffects((fixedEffects) -> {
fixedParticleEffects.addAll(fixedEffects);
});
}
/**
* Removes all fixed effects for the given pplayer
* Gets the PPlayers that are loaded
*
* @param pplayerUUID The pplayer to remove the fixed effects from
* @return The loaded PPlayers
*/
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);
public static List<PPlayer> getPPlayers() {
return particlePlayers;
}
/**
* Adds a fixed effect
*
* @param fixedEffect The fixed effect to add
* Loads all FixedParticleEffects from the database
* Loads all online PPlayers from the database
*/
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
*/
public static void refreshPPlayers() {
public static void refreshData() {
particlePlayers.clear();
for (Player player : Bukkit.getOnlinePlayers())
PPlayerDataManager.getInstance().loadPPlayer(player.getUniqueId());
}
/**
* Overrides an existing PPlayer with the same UUID
*
* @param pplayer The PPlayer to override
*/
public static void updateIfContains(PPlayer pplayer) {
for (PPlayer pp : particlePlayers) {
if (pp.getUniqueId() == pplayer.getUniqueId()) {
particlePlayers.remove(pp);
particlePlayers.add(pplayer);
break;
}
DataManager.loadFixedEffects();
for (Player player : Bukkit.getOnlinePlayers()) {
DataManager.getPPlayer(player.getUniqueId(), (pplayer) -> { }); // Loads the PPlayer from the database
}
}
/**
* Gets an effect type from a string, used for getting ParticleEffects from the saved data
*
* @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 effectFromString(String effectName) {
for (ParticleEffect effect : ParticleEffect.getSupportedEffects()) {
if (effect.getName().equalsIgnoreCase(effectName)) return effect;
}
return null;
}
/**
* The main loop to display all the particles
* Does not display particles if the world is disabled or if the player is in spectator mode
@ -162,9 +92,9 @@ public class ParticleManager extends BukkitRunnable implements Listener {
hue++;
hue %= 360;
if (hue % 10 == 0) { // Only increment note by 2 notes per second
if (hue % 5 == 0) { // Only increment note by 4 notes per second
note++;
note %= 24;
note %= 25;
}
// Loop over backwards so we can remove pplayers if need be
@ -172,85 +102,41 @@ public class ParticleManager extends BukkitRunnable implements Listener {
PPlayer pplayer = particlePlayers.get(i);
Player player = pplayer.getPlayer();
if (player == null) { // Skip and remove, why are they still in the array if they are offline?
particlePlayers.remove(i);
continue;
}
// Perform validity checks
boolean valid = true;
// Don't show their particles if they are in spectator mode
if (player.getGameMode() == GameMode.SPECTATOR) {
valid = false;
}
if (PPlayerDataManager.getInstance().isWorldDisabled(player.getWorld().getName())) {
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);
}
// Don't spawn particles if the world doesn't allow it
if (player != null && player.getGameMode() != GameMode.SPECTATOR && !PermissionManager.isWorldDisabled(player.getWorld().getName()))
for (ParticlePair particles : pplayer.getActiveParticles())
displayParticles(particles, player.getLocation().clone().add(0, 1, 0));
// Loop for FixedParticleEffects
// Don't spawn particles if the world doesn't allow it
for (FixedParticleEffect effect : pplayer.getFixedParticles())
if (!PermissionManager.isWorldDisabled(effect.getLocation().getWorld().getName()))
displayFixedParticleEffect(effect);
}
}
/**
* Displays particles at the given player location with their settings
*
* @param pplayer The PPlayer to use for getting particle settings
* @param particle The ParticlePair to use for getting particle settings
* @param location The location to display at
*/
private void displayParticles(PPlayer pplayer, Location location) {
if (!ParticleStyleManager.isCustomHandled(pplayer.getParticleStyle())) {
ParticleEffect effect = pplayer.getParticleEffect();
if (effect == ParticleEffect.NONE) return;
for (PParticle particle : pplayer.getParticleStyle().getParticles(pplayer, location)) {
if (effect.hasProperty(ParticleProperty.REQUIRES_MATERIAL_DATA)) {
effect.display(pplayer.getParticleSpawnData(), particle.getXOff(), particle.getYOff(), particle.getZOff(), particle.getSpeed(), 1, particle.getLocation(effect.hasProperty(ParticleProperty.COLORABLE)));
} else if (effect.hasProperty(ParticleProperty.COLORABLE)) {
effect.display(pplayer.getParticleSpawnColor(), particle.getLocation(effect.hasProperty(ParticleProperty.COLORABLE)));
} else {
effect.display(particle.getXOff(), particle.getYOff(), particle.getZOff(), particle.getSpeed(), 1, particle.getLocation(effect.hasProperty(ParticleProperty.COLORABLE)));
}
}
}
private void displayParticles(ParticlePair particle, Location location) {
if (!ParticleStyleManager.isCustomHandled(particle.getStyle()))
for (PParticle pparticle : particle.getStyle().getParticles(particle, location))
ParticleEffect.display(particle, pparticle, false);
}
/**
* An alternative method used for custom handled styles
*
* @param pplayer The PPlayer to use for getting particle settings
* @param particle The ParticlePair to use for getting particle settings
* @param particles The particles to display
*/
public static void displayParticles(PPlayer pplayer, PParticle[] particles) {
ParticleEffect effect = pplayer.getParticleEffect();
if (effect == ParticleEffect.NONE) return;
for (PParticle particle : particles) {
if (effect.hasProperty(ParticleProperty.REQUIRES_MATERIAL_DATA)) {
effect.display(pplayer.getParticleSpawnData(), particle.getXOff(), particle.getYOff(), particle.getZOff(), particle.getSpeed(), 1, particle.getLocation(effect.hasProperty(ParticleProperty.COLORABLE)));
} else if (effect.hasProperty(ParticleProperty.COLORABLE)) {
effect.display(pplayer.getParticleSpawnColor(), particle.getLocation(effect.hasProperty(ParticleProperty.COLORABLE)));
} else {
effect.display(particle.getXOff(), particle.getYOff(), particle.getZOff(), particle.getSpeed(), 1, particle.getLocation(effect.hasProperty(ParticleProperty.COLORABLE)));
}
}
public static void displayParticles(ParticlePair particle, List<PParticle> particles) {
for (PParticle pparticle : particles)
ParticleEffect.display(particle, pparticle, false);
}
/**
@ -259,26 +145,47 @@ public class ParticleManager extends BukkitRunnable implements Listener {
* @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_MATERIAL_DATA)) {
effect.display(fixedEffect.getParticleSpawnData(), particle.getXOff(), particle.getYOff(), particle.getZOff(), particle.getSpeed(), 1, particle.getLocation(effect.hasProperty(ParticleProperty.COLORABLE)));
} else if (effect.hasProperty(ParticleProperty.COLORABLE)) {
effect.display(fixedEffect.getParticleSpawnColor(), particle.getLocation(effect.hasProperty(ParticleProperty.COLORABLE)));
} else {
effect.display(particle.getXOff(), particle.getYOff(), particle.getZOff(), particle.getSpeed(), 1, particle.getLocation(effect.hasProperty(ParticleProperty.COLORABLE)));
}
}
ParticlePair particle = fixedEffect.getParticlePair();
for (PParticle pparticle : particle.getStyle().getParticles(particle, fixedEffect.getLocation()))
ParticleEffect.display(particle, pparticle, true);
}
/**
* Gets the rainbow OrdinaryColor for particle spawning with data 'rainbow'
*
* @return The rainbow OrdinaryColor for particle spawning with data 'rainbow'
*/
public static OrdinaryColor getRainbowParticleColor() {
Color rgb = Color.getHSBColor(hue / 360F, 1.0F, 1.0F);
return new OrdinaryColor(rgb.getRed(), rgb.getGreen(), rgb.getBlue());
}
/**
* Gets the rainbow NoteColor for particle spawning with data 'rainbow'
*
* @return The rainbow NoteColor for particle spawning with data 'rainbow'
*/
public static NoteColor getRainbowNoteParticleColor() {
return new NoteColor(note);
}
/**
* Gets a randomized OrdinaryColor for particle spawning with data 'random'
*
* @return A randomized OrdinaryColor for particle spawning with data 'random'
*/
public static OrdinaryColor getRandomParticleColor() {
Color rgb = new Color(RANDOM.nextInt(256), RANDOM.nextInt(256), RANDOM.nextInt(256));
return new OrdinaryColor(rgb.getRed(), rgb.getGreen(), rgb.getBlue());
}
/**
* Gets a randomized NoteColor for particle spawning with data 'random'
*
* @return A randomized NoteColor for particle spawning with data 'random'
*/
public static NoteColor getRandomNoteParticleColor() {
return new NoteColor(RANDOM.nextInt(25));
}
}

View file

@ -1,11 +1,3 @@
/**
* 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.manager;
import java.util.ArrayList;
@ -13,41 +5,168 @@ import java.util.List;
import org.bukkit.entity.Player;
import com.esophose.playerparticles.manager.SettingManager.PSetting;
import com.esophose.playerparticles.particles.PPlayer;
import com.esophose.playerparticles.particles.ParticleEffect;
import com.esophose.playerparticles.styles.DefaultStyles;
import com.esophose.playerparticles.styles.api.ParticleStyle;
import com.esophose.playerparticles.styles.api.ParticleStyleManager;
public class PermissionManager {
private static final String PERMISSION_PREFIX = "playerparticles.";
public enum PPermission {
ALL("*"),
EFFECT_ALL("effect.*"),
EFFECT("effect"),
STYLE_ALL("style.*"),
STYLE("style"),
FIXED("fixed"),
FIXED_UNLIMITED("fixed.unlimited"),
FIXED_CLEAR("fixed.clear"),
RELOAD("reload"),
PARTICLES_UNLIMITED("particles.unlimited"),
GROUPS_UNLIMITED("groups.unlimited");
private final String permissionString;
private PPermission(String permissionString) {
this.permissionString = permissionString;
}
/**
* Checks if a Player has a PlayerParticles permission
*
* @param p The Player
* @return True if the Player has permission
*/
public boolean check(Player p) {
String permission = PERMISSION_PREFIX + this.permissionString;
return p.hasPermission(permission);
}
/**
* Checks if a Player has a PlayerParticles permission with a sub-permission
*
* @param p The Player
* @param subPermission The sub-permission
* @return True if the Player has permission
*/
public boolean check(Player p, String subPermission) {
String permission = PERMISSION_PREFIX + this.permissionString + '.' + subPermission;
return p.hasPermission(permission);
}
}
private PermissionManager() {
}
/**
* Checks if the given player has reached the max number of particles in their active group
*
* @param pplayer The player to check
* @return If the player has reached the max number of particles in their active group
*/
public static boolean hasPlayerReachedMaxParticles(PPlayer pplayer) {
if (PPermission.ALL.check(pplayer.getPlayer())) return false;
if (PPermission.PARTICLES_UNLIMITED.check(pplayer.getPlayer())) return false;
return pplayer.getActiveParticles().size() >= PSetting.MAX_PARTICLES.getInt();
}
/**
* Checks if the given player has reached the max number of saved particle groups
*
* @param pplayer The player to check
* @return If the player has reached the max number of saved particle groups
*/
public static boolean hasPlayerReachedMaxGroups(PPlayer pplayer) {
if (PPermission.ALL.check(pplayer.getPlayer())) return false;
if (PPermission.GROUPS_UNLIMITED.check(pplayer.getPlayer())) return false;
return pplayer.getParticleGroups().size() >= PSetting.MAX_GROUPS.getInt();
}
/**
* Checks if the given player has reached the max number of fixed effects
*
* @param pplayer The player to check
* @return If the player has reached the max number of fixed effects
*/
public static boolean hasPlayerReachedMaxFixedEffects(PPlayer pplayer) {
if (PPermission.ALL.check(pplayer.getPlayer())) return false;
if (PPermission.FIXED_UNLIMITED.check(pplayer.getPlayer())) return false;
return pplayer.getFixedEffectIds().size() >= PSetting.MAX_FIXED_EFFECTS.getInt();
}
/**
* Gets the max distance a fixed effect can be created from the player
*
* @return The max distance a fixed effect can be created from the player
*/
public static int getMaxFixedEffectCreationDistance() {
return PSetting.MAX_FIXED_EFFECT_CREATION_DISTANCE.getInt();
}
/**
* Gets the maximum number of particles a player is allowed to use
*
* @param player The player to check
* @return The maximum number of particles based on the config.yml value, or unlimited
*/
public static int getMaxParticlesAllowed(Player player) {
if (PPermission.ALL.check(player) || PPermission.PARTICLES_UNLIMITED.check(player)) return Integer.MAX_VALUE;
return PSetting.MAX_PARTICLES.getInt();
}
/**
* Checks if a world is disabled for particles to spawn in
*
* @param world The world name to check
* @return True if the world is disabled
*/
public static boolean isWorldDisabled(String world) {
return getDisabledWorlds().contains(world);
}
/**
* Gets all the worlds that are disabled
*
* @return All world names that are disabled
*/
public static List<String> getDisabledWorlds() {
return PSetting.DISABLED_WORLDS.getStringList();
}
/**
* Checks if a player has permission to use an effect
* Always returns true for 'none'
*
* @param player The player to check the permission for
* @param effect The effect to check
* @return True if the player has permission to use the effect
*/
public static boolean hasEffectPermission(Player player, ParticleEffect effect) {
if (player.hasPermission("playerparticles.*") || player.hasPermission("playerparticles.effect.*")) return true;
if (player.hasPermission("playerparticles.effect." + effect.getName())) return true;
if (effect == ParticleEffect.NONE) return true;
return false;
if (PPermission.ALL.check(player) || PPermission.EFFECT_ALL.check(player)) return true;
return PPermission.EFFECT.check(player, effect.getName());
}
/**
* Checks if a player has permission to use a style
* Always returns true for 'none' so they can be reset
* Always returns true for 'normal', a player needs at least one style to apply particles
*
* @param player The player to check the permission for
* @param style The style to check
* @return If the player has permission to use the style
*/
public static boolean hasStylePermission(Player player, ParticleStyle style) {
if (player.hasPermission("playerparticles.*") || player.hasPermission("playerparticles.style.*")) return true;
if (player.hasPermission("playerparticles.style." + style.getName())) return true;
if (style == DefaultStyles.NONE) return true;
return false;
if (style == DefaultStyles.NORMAL) return true;
if (PPermission.ALL.check(player) || PPermission.STYLE_ALL.check(player)) return true;
return PPermission.STYLE.check(player, style.getName());
}
/**
@ -56,11 +175,11 @@ 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> getEffectsUserHasPermissionFor(Player p) {
public static List<String> getEffectNamesUserHasPermissionFor(Player p) {
List<String> list = new ArrayList<String>();
for (ParticleEffect pe : ParticleEffect.getSupportedEffects()) {
if (hasEffectPermission(p, pe)) list.add(pe.getName());
}
for (ParticleEffect pe : ParticleEffect.getSupportedEffects())
if (hasEffectPermission(p, pe))
list.add(pe.getName());
return list;
}
@ -70,22 +189,40 @@ public class PermissionManager {
* @param p The player to get style names for
* @return A String List of all style names the given player has permission for
*/
public static List<String> getStylesUserHasPermissionFor(Player p) {
public static List<String> getStyleNamesUserHasPermissionFor(Player p) {
List<String> list = new ArrayList<String>();
for (ParticleStyle ps : ParticleStyleManager.getStyles()) {
if (hasStylePermission(p, ps)) list.add(ps.getName());
}
for (ParticleStyle ps : ParticleStyleManager.getStyles())
if (hasStylePermission(p, ps))
list.add(ps.getName());
return list;
}
/**
* Gets a List of all effects a player has permission for
*
* @param p The player to get effects for
* @return A List of all effects the given player has permission for
*/
public static List<ParticleEffect> getEffectsUserHasPermissionFor(Player p) {
List<ParticleEffect> list = new ArrayList<ParticleEffect>();
for (ParticleEffect pe : ParticleEffect.getSupportedEffects())
if (hasEffectPermission(p, pe))
list.add(pe);
return list;
}
/**
* Checks if a player has permission to execute commands for other players
* Gets a List of all styles a player has permission for
*
* @param player The player to check the permission for
* @return True if the player has permission
* @param p The player to get styles for
* @return A List of all styles the given player has permission for
*/
public static boolean canUseForceReset(Player player) {
return player.hasPermission("playerparticles.forcereset");
public static List<ParticleStyle> getStylesUserHasPermissionFor(Player p) {
List<ParticleStyle> list = new ArrayList<ParticleStyle>();
for (ParticleStyle ps : ParticleStyleManager.getStyles())
if (hasStylePermission(p, ps))
list.add(ps);
return list;
}
/**
@ -95,7 +232,27 @@ public class PermissionManager {
* @return True if the player has permission
*/
public static boolean canUseFixedEffects(Player player) {
return player.hasPermission("playerparticles.*") || player.hasPermission("playerparticles.fixed");
return PPermission.ALL.check(player) || PPermission.FIXED.check(player);
}
/**
* Checks if a player has permission to clear fixed effects
*
* @param player The player to check the permission for
* @return True if the player has permission to use /pp fixed clear
*/
public static boolean canClearFixedEffects(Player player) {
return PPermission.ALL.check(player) || PPermission.FIXED_CLEAR.check(player);
}
/**
* Checks if a player has permission to use /pp reload
*
* @param player The player to check the permission for
* @return True if the player has permission to reload the plugin's settings
*/
public static boolean canReloadPlugin(Player player) {
return PPermission.ALL.check(player) || PPermission.RELOAD.check(player);
}
}

View file

@ -0,0 +1,266 @@
package com.esophose.playerparticles.manager;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.bukkit.Material;
import com.esophose.playerparticles.PlayerParticles;
import com.esophose.playerparticles.particles.ParticleEffect;
import com.esophose.playerparticles.util.ParticleUtils;
public class SettingManager {
/**
* The types of settings that can be loaded
*/
private enum PSettingType {
BOOLEAN,
INTEGER,
LONG,
DOUBLE,
STRING,
STRING_LIST
}
/**
* An enum containing all settings in the config.yml for the plugin
*/
public enum PSetting {
VERSION(PSettingType.DOUBLE),
TICKS_PER_PARTICLE(PSettingType.LONG),
CHECK_UPDATES(PSettingType.BOOLEAN),
GUI_ENABLED(PSettingType.BOOLEAN),
PARTICLE_RENDER_RANGE_PLAYER(PSettingType.INTEGER),
PARTICLE_RENDER_RANGE_FIXED_EFFECT(PSettingType.INTEGER),
MESSAGES_ENABLED(PSettingType.BOOLEAN),
USE_MESSAGE_PREFIX(PSettingType.BOOLEAN),
MESSAGE_PREFIX(PSettingType.STRING),
DATABASE_ENABLE(PSettingType.BOOLEAN),
DATABASE_HOSTNAME(PSettingType.STRING),
DATABASE_PORT(PSettingType.STRING),
DATABASE_NAME(PSettingType.STRING),
DATABASE_USER_NAME(PSettingType.STRING),
DATABASE_USER_PASSWORD(PSettingType.STRING),
MAX_FIXED_EFFECTS(PSettingType.INTEGER),
MAX_FIXED_EFFECT_CREATION_DISTANCE(PSettingType.INTEGER),
MAX_PARTICLES(PSettingType.INTEGER),
MAX_GROUPS(PSettingType.INTEGER),
DISABLED_WORLDS(PSettingType.STRING_LIST),
LANG_FILE(PSettingType.STRING);
private final PSettingType settingType;
private Object value = null;
private PSetting(PSettingType settingType) {
this.settingType = settingType;
}
/**
* Resets the setting's value so it will be fetched from the config the next time it's needed
*/
private void resetDefault() {
this.value = null;
}
/**
* Gets the value from cache, or the config.yml if it isn't loaded yet
*
* @return The value of this setting
*/
private Object getValue() {
if (this.value == null) {
String configPath = this.name().toLowerCase().replaceAll("_", "-");
switch (this.settingType) {
case BOOLEAN:
this.value = PlayerParticles.getPlugin().getConfig().getBoolean(configPath);
break;
case INTEGER:
this.value = PlayerParticles.getPlugin().getConfig().getInt(configPath);
break;
case LONG:
this.value = PlayerParticles.getPlugin().getConfig().getLong(configPath);
break;
case DOUBLE:
this.value = PlayerParticles.getPlugin().getConfig().getDouble(configPath);
break;
case STRING:
this.value = PlayerParticles.getPlugin().getConfig().getString(configPath);
break;
case STRING_LIST:
this.value = PlayerParticles.getPlugin().getConfig().getStringList(configPath);
break;
}
}
return this.value;
}
/**
* Gets the setting's value as a boolean
*
* @return The setting's value as a boolean
*/
public boolean getBoolean() {
return (boolean) this.getValue();
}
/**
* Gets the setting's value as an int
*
* @return The setting's value as an int
*/
public int getInt() {
return (int) this.getValue();
}
/**
* Gets the setting's value as a long
*
* @return The setting's value as a long
*/
public long getLong() {
return (long) this.getValue();
}
/**
* Gets the setting's value as a double
*
* @return The setting's value as a double
*/
public double getDouble() {
return (double) this.getValue();
}
/**
* Gets the setting's value as a String
*
* @return The setting's value as a String
*/
public String getString() {
return (String) this.getValue();
}
/**
* Gets the setting's value as a List of Strings
*
* @return The setting's value as a List of Strings
*/
@SuppressWarnings("unchecked")
public List<String> getStringList() {
return (List<String>) this.getValue();
}
/**
* Gets the setting's value as a Material
*
* @return The setting's value as a Material
*/
public Material getMaterial() {
return (Material) this.getValue();
}
}
/**
* Used for grabbing/caching configurable GUI Icons from the config.yml
*/
public enum GuiIcon {
PARTICLES,
GROUPS,
PRESET_GROUPS,
BACK,
CREATE,
EDIT_EFFECT,
EDIT_STYLE,
EDIT_DATA,
RANDOMIZE,
RESET,
EFFECT,
STYLE;
private Map<String, Material> materials;
private GuiIcon() {
this.materials = new HashMap<String, Material>();
}
/**
* Gets the Material for this icon from the 'gui-icon.misc' section in the config.yml
* Tries to get from cache first, otherwise loads it
*
* @return The Material for this Icon
*/
public Material get() {
return this.getInternal("gui-icon.misc." + this.name().toLowerCase());
}
/**
* Gets the Material for a subsection of this icon in the config.yml
* Tries to get from cache first, otherwise loads it
*
* @param subsection The name of the icon in the section
* @return The Material for this Icon
*/
public Material get(String subsection) {
return this.getInternal("gui-icon." + this.name().toLowerCase() + "." + subsection);
}
/**
* Gets the Material for this icon
* Tries to get from cache first, otherwise loads it
*
* @param configPath Where to look in the config.yml for the Material name
* @return The path in the config.yml to lookup
*/
private Material getInternal(String configPath) {
Material material = this.materials.get(configPath);
if (material != null)
return material;
List<String> materials = PlayerParticles.getPlugin().getConfig().getStringList(configPath);
try {
if (materials.size() == 1) {
material = ParticleUtils.closestMatch(materials.get(0));
} else {
if (ParticleEffect.VERSION_13) {
material = ParticleUtils.closestMatch(materials.get(0));
} else {
material = ParticleUtils.closestMatch(materials.get(1));
}
}
} catch (Exception e) {
PlayerParticles.getPlugin().getLogger().severe("Missing GUI icon for '" + this.name().toLowerCase() + "'");
}
if (material == null)
material = Material.BARRIER;
this.materials.put(configPath, material);
return material;
}
}
private SettingManager() {
}
/**
* Resets the settings to their default values
*/
public static void reload() {
for (PSetting setting : PSetting.values())
setting.resetDefault();
}
}

View file

@ -1,11 +1,3 @@
/**
* 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.particles;
import java.util.UUID;
@ -14,18 +6,6 @@ import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.World;
import com.esophose.playerparticles.PPlayer;
import com.esophose.playerparticles.manager.PPlayerDataManager;
import com.esophose.playerparticles.manager.ParticleManager;
import com.esophose.playerparticles.particles.ParticleEffect.BlockData;
import com.esophose.playerparticles.particles.ParticleEffect.ItemData;
import com.esophose.playerparticles.particles.ParticleEffect.NoteColor;
import com.esophose.playerparticles.particles.ParticleEffect.OrdinaryColor;
import com.esophose.playerparticles.particles.ParticleEffect.ParticleColor;
import com.esophose.playerparticles.particles.ParticleEffect.ParticleData;
import com.esophose.playerparticles.particles.ParticleEffect.ParticleProperty;
import com.esophose.playerparticles.styles.api.ParticleStyle;
public class FixedParticleEffect {
/**
@ -46,16 +26,7 @@ public class FixedParticleEffect {
/**
* 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;
private ParticlePair particlePair;
/**
* Constructs a new FixedParticleEffect
@ -67,34 +38,12 @@ public class FixedParticleEffect {
* @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 itemData The item data for the effect
* @param blockData The block data for the effect
* @param colorData The color data for the effect
* @param noteColorData The note color data for the effect
* @param particlePair The ParticlePair that represents this FixedParticleEffect's appearance
*/
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) {
public FixedParticleEffect(UUID pplayerUUID, int id, String worldName, double xPos, double yPos, double zPos, ParticlePair particlePair) {
this.pplayerUUID = pplayerUUID;
this.id = id;
this.particleEffect = particleEffect;
this.particleStyle = particleStyle;
this.particleItemData = itemData;
this.particleBlockData = blockData;
this.particleColorData = colorData;
this.particleNoteColorData = noteColorData;
// The PPlayer must be loaded
PPlayerDataManager.getInstance().loadPPlayer(pplayerUUID);
PPlayer owner = PPlayerDataManager.getInstance().getPPlayer(this.pplayerUUID);
// 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();
this.particlePair = particlePair;
World world = Bukkit.getWorld(worldName);
if (world == null) { // Default to the first world in case it doesn't exist
@ -123,127 +72,12 @@ public class FixedParticleEffect {
}
/**
* Gets the particle effect used for this effect
* Gets the ParticlePair, which contains all spawn information about this fixed effect
*
* @return The particle effect used for this effect
* @return The ParticlePair that represents this FixedParticleEffect's appearance
*/
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_MATERIAL_DATA)) {
if (this.particleEffect == ParticleEffect.BLOCK || this.particleEffect == ParticleEffect.FALLING_DUST) {
return particleBlockData;
} else if (this.particleEffect == ParticleEffect.ITEM) {
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 particle data as a string
*
* @return A string of the current effect's data
*/
public String getParticleDataString() {
if (this.particleEffect.hasProperty(ParticleProperty.COLORABLE)) {
if (this.particleEffect == ParticleEffect.NOTE) {
if (this.particleNoteColorData.getValueX() * 24 == 99) {
return "rainbow";
} else {
return (this.particleNoteColorData.getValueX() * 24) + "";
}
} else {
if (this.particleColorData.getRed() == 999 && this.particleColorData.getGreen() == 999 && this.particleColorData.getBlue() == 999) {
return "rainbow";
} else {
return this.particleColorData.getRed() + " " + this.particleColorData.getGreen() + " " + this.particleColorData.getBlue();
}
}
} else if (this.particleEffect.hasProperty(ParticleProperty.REQUIRES_MATERIAL_DATA)) {
if (this.particleEffect == ParticleEffect.BLOCK || this.particleEffect == ParticleEffect.FALLING_DUST) {
return this.particleBlockData.getMaterial().toString().toLowerCase();
} else if (this.particleEffect == ParticleEffect.ITEM) {
return this.particleItemData.getMaterial().toString().toLowerCase();
}
}
return "None";
public ParticlePair getParticlePair() {
return this.particlePair;
}
/**
@ -254,5 +88,18 @@ public class FixedParticleEffect {
public Location getLocation() {
return this.location.clone();
}
/**
* Updates the coordinates of the FixedParticleEffect
*
* @param x The new X coordinate
* @param y The new Y coordinate
* @param z The new Z coordinate
*/
public void setCoordinates(double x, double y, double z) {
this.location.setX(x);
this.location.setY(y);
this.location.setZ(z);
}
}

View file

@ -0,0 +1,214 @@
package com.esophose.playerparticles.particles;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import com.esophose.playerparticles.styles.api.ParticleStyle;
import com.esophose.playerparticles.util.ParticleUtils;
public class PPlayer {
/**
* The UUID of the player
*/
private final UUID playerUUID;
/**
* A List of ParticleGroups this player has, the active particle group has an id of null
*/
private List<ParticleGroup> particleGroups;
/**
* A List of FixedParticleEffects this user has applied
*/
private List<FixedParticleEffect> fixedParticles;
/**
* Constructs a new PPlayer
*
* @param uuid The player UUID
* @param particleGroups The ParticleGroups this PPlayer has
* @param fixedParticles The FixedParticleEffects this PPlayer has
*/
public PPlayer(UUID uuid, List<ParticleGroup> particleGroups, List<FixedParticleEffect> fixedParticles) {
this.playerUUID = uuid;
this.particleGroups = particleGroups;
this.fixedParticles = fixedParticles;
}
/**
* Gets the player's UUID
*
* @return The player's UUID
*/
public UUID getUniqueId() {
return this.playerUUID;
}
/**
* Gets the Player from their UUID
*
* @return The player if they are online, null if they are offline
*/
public Player getPlayer() {
return Bukkit.getPlayer(this.playerUUID);
}
/**
* Get a List of ParticleGroups this user has saved
*
* @return A List of ParticleGroups this player has
*/
public List<ParticleGroup> getParticleGroups() {
return this.particleGroups;
}
/**
* Gets a ParticleGroup this player has by its name
*
* @param name The name of the ParticleGroup
* @return The target named ParticleGroup
*/
public ParticleGroup getParticleGroupByName(String name) {
for (ParticleGroup group : this.particleGroups)
if (group.getName().equalsIgnoreCase(name))
return group;
return null;
}
/**
* Get the effect/style/data for particles this player has set
*
* @return A List of ParticlePairs this player has set
*/
public List<ParticlePair> getActiveParticles() {
return this.getActiveParticleGroup().getParticles();
}
/**
* Get the PPlayer's active ParticleGroup
*
* @return A ParticleGroup of this player's active particles
*/
public ParticleGroup getActiveParticleGroup() {
for (ParticleGroup group : this.particleGroups)
if (group.getName().equals(ParticleGroup.DEFAULT_NAME))
return group;
throw new IllegalStateException("Active particle group does not exist for player with UUID: " + this.getUniqueId());
}
/**
* Get all ParticlePairs with a style matching the input
*
* @param style The style to match
* @return A List of ParticlePairs with a matching style
*/
public List<ParticlePair> getActiveParticlesForStyle(ParticleStyle style) {
List<ParticlePair> matches = new ArrayList<ParticlePair>();
for (ParticlePair pair : this.getActiveParticles())
if (pair.getStyle().equals(style))
matches.add(pair);
return matches;
}
/**
* Get a ParticlePair by its id
*
* @param id The id of the ParticlePair
* @return A ParticlePair with the given id, otherwise null
*/
public ParticlePair getActiveParticle(int id) {
for (ParticlePair particle : this.getActiveParticles())
if (particle.getId() == id)
return particle;
return null;
}
/**
* Get the effect/style/data for all fixed particles this has has set
*
* @return A List of FixedParticleEffects this player has set
*/
public List<FixedParticleEffect> getFixedParticles() {
return this.fixedParticles;
}
/**
* Get a FixedParticleEffect this player owns by id
*
* @param id The id
* @return The FixedParticleEffect the player owns
*/
public FixedParticleEffect getFixedEffectById(int id) {
for (FixedParticleEffect fixedEffect : this.fixedParticles)
if (fixedEffect.getId() == id)
return fixedEffect;
return null;
}
/**
* Gets a list of ids of all fixed effect this player has
*
* @return A List of Integer ids this player's fixed effects have
*/
public List<Integer> getFixedEffectIds() {
List<Integer> ids = new ArrayList<Integer>();
for (FixedParticleEffect fixedEffect : this.fixedParticles)
ids.add(fixedEffect.getId());
return ids;
}
/**
* Adds a fixed effect
*
* @param fixedEffect The fixed effect to add
*/
public void addFixedEffect(FixedParticleEffect fixedEffect) {
this.fixedParticles.add(fixedEffect);
}
/**
* Removes a fixed effect for the given pplayer with the given id
*
* @param id The id of the fixed effect to remove
*/
public void removeFixedEffect(int id) {
for (FixedParticleEffect fixedEffect : this.fixedParticles) {
if (fixedEffect.getId() == id) {
this.fixedParticles.remove(fixedEffect);
break;
}
}
}
/**
* Gets the next Id for a player's fixed effects
*
* @return The next available fixed effect id
*/
public int getNextFixedEffectId() {
List<Integer> fixedEffectIds = this.getFixedEffectIds();
int[] ids = new int[fixedEffectIds.size()];
for (int i = 0; i < fixedEffectIds.size(); i++)
ids[i] = fixedEffectIds.get(i);
return ParticleUtils.getSmallestPositiveInt(ids);
}
/**
* Gets the next Id for a player's active particles
*
* @return The next available active particle id
*/
public int getNextActiveParticleId() {
List<ParticlePair> activeParticles = this.getActiveParticles();
int[] ids = new int[activeParticles.size()];
for (int i = 0; i < activeParticles.size(); i++)
ids[i] = activeParticles.get(i).getId();
return ParticleUtils.getSmallestPositiveInt(ids);
}
}

View file

@ -1,11 +1,3 @@
/**
* 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.particles;
import java.lang.reflect.Constructor;
@ -26,13 +18,12 @@ import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.material.MaterialData;
/**
* Heavily modified to work with the Spigot Particle API
*
* @author Esophose
*/
import com.esophose.playerparticles.manager.SettingManager.PSetting;
import com.esophose.playerparticles.styles.api.PParticle;
@SuppressWarnings("deprecation")
public enum ParticleEffect {
// Ordered and named by their Minecraft 1.13 internal names
AMBIENT_ENTITY_EFFECT("SPELL_MOB_AMBIENT", "SPELL_MOB_AMBIENT", ParticleProperty.COLORABLE),
ANGRY_VILLAGER("VILLAGER_ANGRY", "VILLAGER_ANGRY"),
@ -50,7 +41,7 @@ public enum ParticleEffect {
DRIPPING_LAVA("DRIP_LAVA", "DRIP_LAVA"),
DRIPPING_WATER("DRIP_WATER", "DRIP_WATER"),
DUST("REDSTONE", "REDSTONE", ParticleProperty.COLORABLE),
//ELDER_GUARDIAN("MOB_APPEARANCE", "MOB_APPEARANCE"), // No thank you
// ELDER_GUARDIAN("MOB_APPEARANCE", "MOB_APPEARANCE"), // No thank you
ENCHANT("ENCHANTMENT_TABLE", "ENCHANTMENT_TABLE"),
ENCHANTED_HIT("CRIT_MAGIC", "CRIT_MAGIC"),
END_ROD("END_ROD", "END_ROD"),
@ -65,14 +56,13 @@ public enum ParticleEffect {
HAPPY_VILLAGER("VILLAGER_HAPPY", "VILLAGER_HAPPY"),
HEART("HEART", "HEART"),
INSTANT_EFFECT("SPELL_INSTANT", "SPELL_INSTANT"),
ITEM("ITEM_CRACK", "ITEM_CRACK", ParticleProperty.REQUIRES_MATERIAL_DATA),
ITEM("ITEM_CRACK", "ITEM_CRACK", ParticleProperty.REQUIRES_MATERIAL_DATA),
ITEM_SLIME("SLIME", "SLIME"),
ITEM_SNOWBALL("SNOWBALL", "SNOWBALL"),
LARGE_SMOKE("SMOKE_LARGE", "SMOKE_LARGE"),
LAVA("LAVA", "LAVA"),
MYCELIUM("TOWN_AURA", "TOWN_AURA"),
NAUTILUS("NAUTILUS", null),
NONE("", ""), // Custom effect to represent none selected
NOTE("NOTE", "NOTE", ParticleProperty.COLORABLE),
POOF("EXPLOSION_NORMAL", "EXPLOSION_NORMAL"), // The 1.13 combination of explode and showshovel
PORTAL("PORTAL", "PORTAL"),
@ -86,10 +76,9 @@ public enum ParticleEffect {
TOTEM_OF_UNDYING("TOTEM", "TOTEM"),
UNDERWATER("SUSPENDED_DEPTH", "SUSPENDED_DEPTH"),
WITCH("SPELL_WITCH", "SPELL_WTICH");
private static final int PARTICLE_DISPLAY_RANGE_SQUARED = 36864; // (12 chunks * 16 blocks per chunk)^2
public static boolean VERSION_13; // This is a particle unique to Minecraft 1.13, this is a reliable way of telling what server version is running
private static final Map<String, ParticleEffect> NAME_MAP = new HashMap<String, ParticleEffect>();
private static boolean VERSION_13; // This is a particle unique to Minecraft 1.13, this is a reliable way of telling what server version is running
private static Constructor<?> DustOptions_CONSTRUCTOR;
private static Method createBlockData_METHOD;
private final Particle internalEnum;
@ -101,12 +90,12 @@ public enum ParticleEffect {
for (ParticleEffect effect : values()) {
NAME_MAP.put(effect.getName(), effect);
}
try {
VERSION_13 = Particle.valueOf("NAUTILUS") != null;
DustOptions_CONSTRUCTOR = Particle.REDSTONE.getDataType().getConstructor(Color.class, float.class);
createBlockData_METHOD = Material.class.getMethod("createBlockData");
} catch (Exception e) {
} catch (Exception e) {
DustOptions_CONSTRUCTOR = null;
createBlockData_METHOD = null;
VERSION_13 = false;
@ -116,8 +105,8 @@ public enum ParticleEffect {
/**
* Construct a new particle effect
*
* @param enumName Name of the Particle Enum when the server version is >= 1.13
* @param enumNameLegacy Name of the Particle Enum when the server version is < 1.13
* @param enumName Name of the Particle Enum when the server version is greater than or equal to 1.13
* @param enumNameLegacy Name of the Particle Enum when the server version is less than 1.13
* @param properties Properties of this particle effect
*/
private ParticleEffect(String enumName, String enumNameLegacy, ParticleProperty... properties) {
@ -130,7 +119,7 @@ public enum ParticleEffect {
break;
}
}
this.internalEnum = matchingEnum; // Will be null if this server's version doesn't support this particle type
}
@ -169,7 +158,7 @@ public enum ParticleEffect {
* @return Whether the particle effect is supported or not
*/
public boolean isSupported() {
return this == NONE || this.internalEnum != null;
return this.internalEnum != null;
}
/**
@ -199,27 +188,25 @@ public enum ParticleEffect {
}
return null;
}
/**
* Determine if the data type for a particle effect is correct
* Invokes the correct spawn method for the particle information given
*
* @param effect Particle effect
* @param data Particle data
* @return Whether the data type is correct or not
* @param particle The ParticlePair, given the effect/style/data
* @param pparticle The particle spawn information
* @param isFixedEffect If the particle is spawned from a fixed effect
*/
private static boolean isDataCorrect(ParticleEffect effect, ParticleData data) {
return ((effect == BLOCK || effect == FALLING_DUST) && data instanceof BlockData) || (effect == ITEM && data instanceof ItemData);
}
/**
* Determine if the color type for a particle effect is correct
*
* @param effect Particle effect
* @param color Particle color
* @return Whether the color type is correct or not
*/
private static boolean isColorCorrect(ParticleEffect effect, ParticleColor color) {
return ((effect == ENTITY_EFFECT || effect == AMBIENT_ENTITY_EFFECT || effect == DUST) && color instanceof OrdinaryColor) || (effect == NOTE && color instanceof NoteColor);
public static void display(ParticlePair particle, PParticle pparticle, boolean isFixedEffect) {
ParticleEffect effect = particle.getEffect();
int count = pparticle.isDirectional() ? 0 : 1;
if (effect.hasProperty(ParticleProperty.REQUIRES_MATERIAL_DATA)) {
effect.display(particle.getSpawnMaterial(), pparticle.getXOff(), pparticle.getYOff(), pparticle.getZOff(), pparticle.getSpeed(), 1, pparticle.getLocation(effect.hasProperty(ParticleProperty.COLORABLE)), isFixedEffect);
} else if (effect.hasProperty(ParticleProperty.COLORABLE)) {
effect.display(particle.getSpawnColor(), pparticle.getLocation(effect.hasProperty(ParticleProperty.COLORABLE)), isFixedEffect);
} else {
effect.display(pparticle.getXOff(), pparticle.getYOff(), pparticle.getZOff(), pparticle.getSpeed(), count, pparticle.getLocation(effect.hasProperty(ParticleProperty.COLORABLE)), isFixedEffect);
}
}
/**
@ -231,15 +218,17 @@ public enum ParticleEffect {
* @param speed Display speed of the particles
* @param amount Amount of particles
* @param center Center location of the effect
* @param isFixedEffect If the particle is spawned from a fixed effect
* @throws ParticleDataException If the particle effect requires additional data
*/
public void display(float offsetX, float offsetY, float offsetZ, float speed, int amount, Location center) throws ParticleDataException {
public void display(double offsetX, double offsetY, double offsetZ, double speed, int amount, Location center, boolean isFixedEffect) throws ParticleDataException {
if (hasProperty(ParticleProperty.REQUIRES_MATERIAL_DATA)) {
throw new ParticleDataException("This particle effect requires additional data");
}
for (Player player : getPlayersInRange(center))
for (Player player : getPlayersInRange(center, isFixedEffect)) {
player.spawnParticle(internalEnum, center.getX(), center.getY(), center.getZ(), amount, offsetX, offsetY, offsetZ, speed);
}
}
/**
@ -247,29 +236,29 @@ public enum ParticleEffect {
*
* @param color Color of the particle
* @param center Center location of the effect
* @param isFixedEffect If the particle is spawned from a fixed effect
* @throws ParticleColorException If the particle effect is not colorable or the color type is incorrect
*/
public void display(ParticleColor color, Location center) throws ParticleColorException {
public void display(ParticleColor color, Location center, boolean isFixedEffect) throws ParticleColorException {
if (!hasProperty(ParticleProperty.COLORABLE)) {
throw new ParticleColorException("This particle effect is not colorable");
}
if (!isColorCorrect(this, color)) {
throw new ParticleColorException("The particle color type is incorrect");
}
if (this == DUST && VERSION_13) { // DUST uses a special data object for spawning in 1.13
OrdinaryColor dustColor = (OrdinaryColor)color;
OrdinaryColor dustColor = (OrdinaryColor) color;
Object dustData = null;
try { // The DustData class doesn't exist in Minecraft versions less than 1.13... so this is disgusting... but it works great
dustData = DustOptions_CONSTRUCTOR.newInstance(Color.fromRGB(dustColor.getRed(), dustColor.getGreen(), dustColor.getBlue()), 1); // Wait, you can change the size of these now??? AWESOME! I might implement this in the future!
} catch (Exception e) { }
for (Player player : getPlayersInRange(center)) {
} catch (Exception e) {
}
for (Player player : getPlayersInRange(center, isFixedEffect)) {
player.spawnParticle(internalEnum, center.getX(), center.getY(), center.getZ(), 1, 0, 0, 0, 0, dustData);
}
} else {
for (Player player : getPlayersInRange(center)) {
// Minecraft clients require that you pass a non-zero value if the Red value should be zero
for (Player player : getPlayersInRange(center, isFixedEffect)) {
// Minecraft clients require that you pass a non-zero value if the Red value should be zero
player.spawnParticle(internalEnum, center.getX(), center.getY(), center.getZ(), 0, this == ParticleEffect.DUST && color.getValueX() == 0 ? Float.MIN_VALUE : color.getValueX(), color.getValueY(), color.getValueZ(), 1);
}
}
@ -280,53 +269,55 @@ public enum ParticleEffect {
* visible for all players within a certain range in the world of @param
* center
*
* @param data Data of the effect
* @param spawnMaterial Material of the effect
* @param offsetX Maximum distance particles can fly away from the center on the x-axis
* @param offsetY Maximum distance particles can fly away from the center on the y-axis
* @param offsetZ Maximum distance particles can fly away from the center on the z-axis
* @param speed Display speed of the particles
* @param amount Amount of particles
* @param center Center location of the effect
* @param isFixedEffect If the particle is spawned from a fixed effect
* @throws ParticleDataException If the particle effect does not require additional data or if the data type is incorrect
*/
public void display(ParticleData data, float offsetX, float offsetY, float offsetZ, float speed, int amount, Location center) throws ParticleDataException {
public void display(Material spawnMaterial, double offsetX, double offsetY, double offsetZ, double speed, int amount, Location center, boolean isFixedEffect) throws ParticleDataException {
if (!hasProperty(ParticleProperty.REQUIRES_MATERIAL_DATA)) {
throw new ParticleDataException("This particle effect does not require additional data");
}
if (!isDataCorrect(this, data)) {
throw new ParticleDataException("The particle data type is incorrect");
}
Object extraData = null;
if (internalEnum.getDataType().getTypeName().equals("org.bukkit.block.data.BlockData")) {
if (internalEnum.getDataType().getTypeName().equals("org.bukkit.block.data.BlockData")) {
try { // The Material.createBlockData() method doesn't exist in Minecraft versions less than 1.13... so this is disgusting... but it works great
extraData = createBlockData_METHOD.invoke(data.getMaterial());
} catch (Exception e) { }
extraData = createBlockData_METHOD.invoke(spawnMaterial);
} catch (Exception e) {
}
} else if (internalEnum.getDataType() == ItemStack.class) {
extraData = new ItemStack(data.getMaterial());
extraData = new ItemStack(spawnMaterial);
} else if (internalEnum.getDataType() == MaterialData.class) {
extraData = new MaterialData(data.getMaterial()); // Deprecated, only used in versions < 1.13
extraData = new MaterialData(spawnMaterial); // Deprecated, only used in versions < 1.13
} else {
System.out.println(internalEnum.getDataType());
extraData = null;
}
for (Player player : getPlayersInRange(center))
for (Player player : getPlayersInRange(center, isFixedEffect))
player.spawnParticle(internalEnum, center.getX(), center.getY(), center.getZ(), amount, offsetX, offsetY, offsetZ, speed, extraData);
}
/**
* Gets a List<Player> of players within the particle display range
* Gets a List of Players within the particle display range
*
* @param center The center of the radius to check around
* @return A List<Player> of the players within the particle display range
* @param isFixedEffect If the particle is spawned from a fixed effect
* @return A List of Players within the particle display range
*/
private List<Player> getPlayersInRange(Location center) {
private List<Player> getPlayersInRange(Location center, boolean isFixedEffect) {
List<Player> players = new ArrayList<Player>();
for (Player p : Bukkit.getOnlinePlayers())
if (p.getWorld().equals(center.getWorld()) && center.distanceSquared(p.getLocation()) <= PARTICLE_DISPLAY_RANGE_SQUARED)
int range = !isFixedEffect ? PSetting.PARTICLE_RENDER_RANGE_PLAYER.getInt() : PSetting.PARTICLE_RENDER_RANGE_FIXED_EFFECT.getInt();
for (Player p : Bukkit.getOnlinePlayers())
if (p.getWorld().equals(center.getWorld()) && center.distanceSquared(p.getLocation()) <= range * range)
players.add(p);
return players;
}
@ -350,83 +341,6 @@ public enum ParticleEffect {
COLORABLE;
}
/**
* Represents the particle data for effects like
* {@link ParticleEffect#ITEM}, {@link ParticleEffect#BLOCK}, and {@link ParticleEffect#FALLING_DUST}
* <p>
* This class is part of the <b>ParticleEffect Library</b> and follows the
* same usage conditions
*
* @author DarkBlade12
* @since 1.6
*/
public static abstract class ParticleData {
private final Material material;
/**
* Construct a new particle data
*
* @param material Material of the item/block
*/
public ParticleData(Material material) {
this.material = material;
}
/**
* Returns the material of this data
*
* @return The material
*/
public Material getMaterial() {
return material;
}
}
/**
* Represents the item data for the {@link ParticleEffect#ITEM} effect
* <p>
* This class is part of the <b>ParticleEffect Library</b> and follows the
* same usage conditions
*
* @author DarkBlade12
* @since 1.6
*/
public static final class ItemData extends ParticleData {
/**
* Construct a new item data
*
* @param material Material of the item
*/
public ItemData(Material material) {
super(material);
}
}
/**
* Represents the block data for the {@link ParticleEffect#BLOCK} and
* {@link ParticleEffect#FALLING_DUST} effects
* <p>
* This class is part of the <b>ParticleEffect Library</b> and follows the
* same usage conditions
*
* @author DarkBlade12
* @since 1.6
*/
public static final class BlockData extends ParticleData {
/**
* Construct a new block data
*
* @param material Material of the block
* @throws IllegalArgumentException If the material is not a block
*/
public BlockData(Material material) throws IllegalArgumentException {
super(material);
if (!material.isBlock()) {
throw new IllegalArgumentException("The material is not a block");
}
}
}
/**
* Represents the color for effects like {@link ParticleEffect#ENTITY_EFFECT},
* {@link ParticleEffect#AMBIENT_ENTITY_EFFECT}, {@link ParticleEffect#DUST}
@ -486,7 +400,7 @@ public enum ParticleEffect {
* or higher than 255
*/
public OrdinaryColor(int red, int green, int blue) throws IllegalArgumentException {
if (red == 999 && green == 999 && blue == 999) {
if ((red == 999 && green == 999 && blue == 999) || (red == 998 && green == 998 && blue == 998)) { // Allow rainbow and random values
this.red = red;
this.green = green;
this.blue = blue;
@ -549,7 +463,7 @@ public enum ParticleEffect {
*/
@Override
public float getValueX() {
if (red == 999) return 0F;
if (red == 999 || red == 998) return 0F;
return (float) red / 255F;
}
@ -560,7 +474,7 @@ public enum ParticleEffect {
*/
@Override
public float getValueY() {
if (green == 999) return 0F;
if (green == 999 || green == 998) return 0F;
return (float) green / 255F;
}
@ -571,7 +485,7 @@ public enum ParticleEffect {
*/
@Override
public float getValueZ() {
if (blue == 999) return 0F;
if (blue == 999 || blue == 998) return 0F;
return (float) blue / 255F;
}
}
@ -596,7 +510,7 @@ public enum ParticleEffect {
* higher than 24
*/
public NoteColor(int note) throws IllegalArgumentException {
if (note == 99) {
if (note == 99 || note == 98) { // Allow rainbow and random values
this.note = note;
} else {
if (note < 0) {
@ -609,6 +523,15 @@ public enum ParticleEffect {
}
}
/**
* Returns the note value
*
* @return The note value
*/
public int getNote() {
return this.note;
}
/**
* Returns the note value divided by 24
*
@ -616,7 +539,7 @@ public enum ParticleEffect {
*/
@Override
public float getValueX() {
return (float) note / 24F;
return (float) this.note / 24F;
}
/**

View file

@ -0,0 +1,267 @@
package com.esophose.playerparticles.particles;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map.Entry;
import java.util.Set;
import java.util.stream.Collectors;
import org.bukkit.Material;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player;
import com.esophose.playerparticles.PlayerParticles;
import com.esophose.playerparticles.manager.PermissionManager;
import com.esophose.playerparticles.particles.ParticleEffect.NoteColor;
import com.esophose.playerparticles.particles.ParticleEffect.OrdinaryColor;
import com.esophose.playerparticles.particles.ParticleEffect.ParticleProperty;
import com.esophose.playerparticles.styles.api.ParticleStyle;
import com.esophose.playerparticles.util.ParticleUtils;
public class ParticleGroup {
public static final String DEFAULT_NAME = "active";
private static HashMap<ParticleGroup, Material> presetGroups;
private String name;
private List<ParticlePair> particles;
public ParticleGroup(String name, List<ParticlePair> particles) {
this.name = name;
this.particles = particles;
}
/**
* Get the player-given name of this ParticleGroup
* This will be null if it's the player's active ParticleGroup
*
* @return The name of this group
*/
public String getName() {
return this.name;
}
/**
* Get the List of ParticlePairs in this group
*
* @return The particles in this group
*/
public List<ParticlePair> getParticles() {
return this.particles;
}
/**
* Checks if a Player can use this ParticleGroup
*
* @param player The Player
* @return True if the Player can use this ParticleGroup
*/
public boolean canPlayerUse(Player player) {
if (PermissionManager.getMaxParticlesAllowed(player) < this.particles.size()) return false;
for (ParticlePair particle : this.particles) {
if (!PermissionManager.hasEffectPermission(player, particle.getEffect())) return false;
if (!PermissionManager.hasStylePermission(player, particle.getStyle())) return false;
}
return true;
}
/**
* Gets an empty ParticleGroup
*
* @return The default empty active ParticleGroup
*/
public static ParticleGroup getDefaultGroup() {
return new ParticleGroup(DEFAULT_NAME, new ArrayList<ParticlePair>());
}
/**
* Loads the preset groups from the groups.yml file
*/
public static void reload() {
presetGroups = new HashMap<ParticleGroup, Material>();
File pluginDataFolder = PlayerParticles.getPlugin().getDataFolder();
File groupsFile = new File(pluginDataFolder.getAbsolutePath() + File.separator + "groups.yml");
// Create the file if it doesn't exist
if (!groupsFile.exists()) {
try (InputStream inStream = PlayerParticles.getPlugin().getResource("groups.yml")) {
Files.copy(inStream, Paths.get(groupsFile.getAbsolutePath()));
} catch (IOException e) {
e.printStackTrace();
}
}
// Parse groups.yml file
YamlConfiguration groupsYaml = YamlConfiguration.loadConfiguration(groupsFile);
Set<String> groupNames = groupsYaml.getKeys(false);
for (String groupName : groupNames) {
try {
List<ParticlePair> particles = new ArrayList<ParticlePair>();
Material iconMaterial = null;
ConfigurationSection groupSection = groupsYaml.getConfigurationSection(groupName);
Set<String> particleKeys = groupSection.getKeys(false);
for (String stringId : particleKeys) {
if (stringId.equalsIgnoreCase("icon")) {
iconMaterial = Material.valueOf(groupSection.getString("icon"));
continue;
}
ConfigurationSection particleSection = groupSection.getConfigurationSection(stringId);
int id = Integer.parseInt(stringId);
ParticleEffect effect = ParticleEffect.fromName(particleSection.getString("effect"));
ParticleStyle style = ParticleStyle.fromName(particleSection.getString("style"));
if (effect == null) {
PlayerParticles.getPlugin().getLogger().severe("Invalid effect name: '" + particleSection.getString("effect") + "'!");
throw new Exception();
}
if (style == null) {
PlayerParticles.getPlugin().getLogger().severe("Invalid style name: '" + particleSection.getString("style") + "'!");
throw new Exception();
}
Material itemData = null;
Material blockData = null;
OrdinaryColor colorData = null;
NoteColor noteColorData = null;
String dataString = particleSection.getString("data");
if (!dataString.isEmpty()) {
String[] args = dataString.split(" ");
if (effect.hasProperty(ParticleProperty.COLORABLE)) {
if (effect == ParticleEffect.NOTE) {
if (args[0].equalsIgnoreCase("rainbow")) {
noteColorData = new NoteColor(99);
} else {
int note = -1;
try {
note = Integer.parseInt(args[0]);
} catch (Exception e) {
PlayerParticles.getPlugin().getLogger().severe("Invalid note: '" + args[0] + "'!");
throw new Exception();
}
if (note < 0 || note > 23) {
PlayerParticles.getPlugin().getLogger().severe("Invalid note: '" + args[0] + "'!");
throw new Exception();
}
noteColorData = new NoteColor(note);
}
} else {
if (args[0].equalsIgnoreCase("rainbow")) {
colorData = new OrdinaryColor(999, 999, 999);
} else {
int r = -1;
int g = -1;
int b = -1;
try {
r = Integer.parseInt(args[0]);
g = Integer.parseInt(args[1]);
b = Integer.parseInt(args[2]);
} catch (Exception e) {
PlayerParticles.getPlugin().getLogger().severe("Invalid color: '" + args[0] + " " + args[1] + " " + args[2] + "'!");
throw new Exception();
}
if (r < 0 || r > 255 || g < 0 || g > 255 || b < 0 || b > 255) {
PlayerParticles.getPlugin().getLogger().severe("Invalid color: '" + args[0] + " " + args[1] + " " + args[2] + "'!");
throw new Exception();
}
colorData = new OrdinaryColor(r, g, b);
}
}
} else if (effect.hasProperty(ParticleProperty.REQUIRES_MATERIAL_DATA)) {
if (effect == ParticleEffect.BLOCK || effect == ParticleEffect.FALLING_DUST) {
try {
blockData = ParticleUtils.closestMatch(args[0]);
if (blockData == null || !blockData.isBlock()) throw new Exception();
} catch (Exception e) {
PlayerParticles.getPlugin().getLogger().severe("Invalid block: '" + args[0] + "'!");
throw new Exception();
}
} else if (effect == ParticleEffect.ITEM) {
try {
itemData = ParticleUtils.closestMatch(args[0]);
if (itemData == null || itemData.isBlock()) throw new Exception();
} catch (Exception e) {
PlayerParticles.getPlugin().getLogger().severe("Invalid item: '" + args[0] + "'!");
throw new Exception();
}
}
}
}
particles.add(new ParticlePair(null, id, effect, style, blockData, blockData, colorData, noteColorData));
}
if (iconMaterial == null) {
PlayerParticles.getPlugin().getLogger().severe("Missing icon for group '" + groupName + "'! Defaulting to ENDER_CHEST");
iconMaterial = Material.ENDER_CHEST;
}
presetGroups.put(new ParticleGroup(groupName, particles), iconMaterial);
} catch (Exception ex) {
PlayerParticles.getPlugin().getLogger().severe("An error occurred while parsing the groups.yml file!");
}
}
}
/**
* Gets all the preset ParticleGroups ordered for display in the GUI
*
* @param player The player
* @return a List of preset ParticleGroups the player can use
*/
public static List<Entry<ParticleGroup, Material>> getPresetGroupsForGUIForPlayer(Player player) {
List<Entry<ParticleGroup, Material>> groups = new ArrayList<Entry<ParticleGroup, Material>>();
List<ParticleGroup> orderedGroups = new ArrayList<ParticleGroup>();
orderedGroups.addAll(presetGroups.keySet());
orderedGroups.sort(Comparator.comparing(ParticleGroup::getName));
for (ParticleGroup group : orderedGroups)
if (group.canPlayerUse(player))
groups.add(new AbstractMap.SimpleEntry<ParticleGroup, Material>(group, presetGroups.get(group)));
return groups;
}
/**
* Gets all the preset ParticleGroups that a player can use
*
* @param player The player
* @return a List of preset ParticleGroups the player can use
*/
public static List<ParticleGroup> getPresetGroupsForPlayer(Player player) {
return presetGroups.keySet().stream().filter(x -> x.canPlayerUse(player)).collect(Collectors.toList());
}
/**
* Gets a preset ParticleGroup by its name
*
* @param groupName The ParticleGroup name
* @return The preset ParticleGroup if it exists, otherwise null
*/
public static ParticleGroup getPresetGroup(String groupName) {
for (ParticleGroup group : presetGroups.keySet())
if (group.getName().equalsIgnoreCase(groupName))
return group;
return null;
}
}

View file

@ -0,0 +1,306 @@
package com.esophose.playerparticles.particles;
import java.util.UUID;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import com.esophose.playerparticles.manager.LangManager;
import com.esophose.playerparticles.manager.LangManager.Lang;
import com.esophose.playerparticles.manager.ParticleManager;
import com.esophose.playerparticles.particles.ParticleEffect.NoteColor;
import com.esophose.playerparticles.particles.ParticleEffect.OrdinaryColor;
import com.esophose.playerparticles.particles.ParticleEffect.ParticleColor;
import com.esophose.playerparticles.particles.ParticleEffect.ParticleProperty;
import com.esophose.playerparticles.styles.DefaultStyles;
import com.esophose.playerparticles.styles.api.ParticleStyle;
import com.esophose.playerparticles.util.ParticleUtils;
public class ParticlePair {
private UUID ownerUUID;
private int id;
private ParticleEffect effect;
private ParticleStyle style;
private Material itemMaterial;
private Material blockMaterial;
private OrdinaryColor color;
private NoteColor noteColor;
public ParticlePair(UUID ownerUUID, int id, ParticleEffect effect, ParticleStyle style, Material itemMaterial, Material blockMaterial, OrdinaryColor color, NoteColor noteColor) {
this.ownerUUID = ownerUUID;
this.id = id;
this.effect = effect;
this.style = style;
this.setEffect(effect);
this.setStyle(style);
this.setItemMaterial(itemMaterial);
this.setBlockMaterial(blockMaterial);
this.setColor(color);
this.setNoteColor(noteColor);
}
/**
* Sets the player's particle effect
*
* @param effect The player's new particle effect
*/
public void setEffect(ParticleEffect effect) {
if (effect == null)
this.effect = getDefault().getEffect();
else
this.effect = effect;
}
/**
* Sets the player's particle style
*
* @param style The player's new particle style
*/
public void setStyle(ParticleStyle style) {
if (style == null)
this.style = getDefault().getStyle();
else
this.style = style;
}
/**
* Sets the player's item material
*
* @param itemMaterial The player's new item material
*/
public void setItemMaterial(Material itemMaterial) {
if (itemMaterial == null || itemMaterial.isBlock())
this.itemMaterial = getDefault().getItemMaterial();
else
this.itemMaterial = itemMaterial;
}
/**
* Sets the player's block material
*
* @param blockMaterial The player's new block material
*/
public void setBlockMaterial(Material blockMaterial) {
if (blockMaterial == null || !blockMaterial.isBlock())
this.blockMaterial = getDefault().getBlockMaterial();
else
this.blockMaterial = blockMaterial;
}
/**
* Sets the player's color data
*
* @param colorData The player's new color data
*/
public void setColor(OrdinaryColor colorData) {
if (colorData == null)
this.color = getDefault().getColor();
else
this.color = colorData;
}
/**
* Sets the player's note color data
*
* @param noteColorData The player's new note color data
*/
public void setNoteColor(NoteColor noteColorData) {
if (noteColorData == null)
this.noteColor = getDefault().getNoteColor();
else
this.noteColor = noteColorData;
}
/**
* Get the UUID of the PPlayer that owns this ParticlePair
*
* @return The owner's UUID
*/
public UUID getOwnerUniqueId() {
return this.ownerUUID;
}
/**
* Get the id of this particle
*
* @return The id of this particle
*/
public int getId() {
return this.id;
}
/**
* Get the ParticleEffect that this ParticlePair represents
*
* @return The effect
*/
public ParticleEffect getEffect() {
return this.effect;
}
/**
* Get the ParticleStyle that this ParticlePair represents
*
* @return The style
*/
public ParticleStyle getStyle() {
return this.style;
}
/**
* Get the item Material this particle uses
*
* @return The item Material
*/
public Material getItemMaterial() {
return this.itemMaterial;
}
/**
* Get the block Material this particle uses
*
* @return The block Material
*/
public Material getBlockMaterial() {
return this.blockMaterial;
}
/**
* Get the color this particle uses
*
* @return The color
*/
public OrdinaryColor getColor() {
return this.color;
}
/**
* Get the note color this particle uses
*
* @return The note color
*/
public NoteColor getNoteColor() {
return this.noteColor;
}
/**
* Gets the color the current particle effect will spawn with
*
* @return Gets the ParticleColor the current particle effect will spawn with
*/
public ParticleColor getSpawnColor() {
if (this.effect.hasProperty(ParticleProperty.COLORABLE)) {
if (this.effect == ParticleEffect.NOTE) {
if (this.noteColor.getNote() == 99) {
return ParticleManager.getRainbowNoteParticleColor();
} else if (this.noteColor.getNote() == 98) {
return ParticleManager.getRandomNoteParticleColor();
}
return this.noteColor;
} else {
if (this.color.getRed() == 999 && this.color.getGreen() == 999 && this.color.getBlue() == 999) {
return ParticleManager.getRainbowParticleColor();
} else if (this.color.getRed() == 998 && this.color.getGreen() == 998 && this.color.getBlue() == 998) {
return ParticleManager.getRandomParticleColor();
} else {
return this.color;
}
}
}
return null;
}
/**
* Gets the material the current particle effect will spawn with
*
* @return The Material the current particle effect requires
*/
public Material getSpawnMaterial() {
if (this.effect.hasProperty(ParticleProperty.REQUIRES_MATERIAL_DATA)) {
if (this.effect == ParticleEffect.ITEM) {
return this.itemMaterial;
} else {
return this.blockMaterial;
}
}
return null;
}
/**
* Gets the current particle data as a string
*
* @return The particle data in a human-readable string
*/
public String getDataString() {
if (this.effect == ParticleEffect.BLOCK || this.effect == ParticleEffect.FALLING_DUST) {
return this.blockMaterial.toString().toLowerCase();
} else if (this.effect == ParticleEffect.ITEM) {
return this.itemMaterial.toString().toLowerCase();
} else if (this.effect.hasProperty(ParticleProperty.COLORABLE)) {
if (this.effect == ParticleEffect.NOTE) {
if (this.noteColor.getNote() == 99) {
return LangManager.getText(Lang.RAINBOW);
} else if (this.noteColor.getNote() == 98) {
return LangManager.getText(Lang.RANDOM);
}
return LangManager.getText(Lang.GUI_SELECT_DATA_NOTE, this.noteColor.getNote());
} else {
if (this.color.getRed() == 999 && this.color.getGreen() == 999 && this.color.getBlue() == 999) {
return LangManager.getText(Lang.RAINBOW);
} else if (this.color.getRed() == 998 && this.color.getGreen() == 998 && this.color.getBlue() == 998) {
return LangManager.getText(Lang.RANDOM);
} else {
return ChatColor.RED + "" + this.color.getRed() + " " + ChatColor.GREEN + this.color.getGreen() + " " + ChatColor.AQUA + this.color.getBlue();
}
}
}
return LangManager.getText(Lang.GUI_DATA_NONE);
}
/**
* Gets a copy of this ParticlePair
*/
public ParticlePair clone() {
return new ParticlePair(this.ownerUUID, this.id, this.effect, this.style, this.itemMaterial, this.blockMaterial, this.color, this.noteColor);
}
/**
* Gets a ParticlePair with the default values applied
* Used for getting internal default values in the cases that null is specified
*
* @return A ParticlePair with default values
*/
private static ParticlePair getDefault() {
return new ParticlePair(null, // @formatter:off
-1,
ParticleEffect.FLAME,
DefaultStyles.NORMAL,
ParticleUtils.closestMatchWithFallback("IRON_SHOVEL", "IRON_SPADE"),
Material.STONE,
new OrdinaryColor(0, 0, 0),
new NoteColor(0)); // @formatter:on
}
/**
* Gets a ParticlePair for a PPlayer with the default values applied
*
* @param pplayer The PPlayer that will own this ParticlePair
* @return A ParticlePair with default values
*/
public static ParticlePair getNextDefault(PPlayer pplayer) {
return new ParticlePair(pplayer.getUniqueId(), // @formatter:off
pplayer.getNextActiveParticleId(),
ParticleEffect.FLAME,
DefaultStyles.NORMAL,
ParticleUtils.closestMatchWithFallback("IRON_SHOVEL", "IRON_SPADE"),
Material.STONE,
new OrdinaryColor(0, 0, 0),
new NoteColor(0)); // @formatter:on
}
}

View file

@ -15,24 +15,31 @@ public class DefaultStyles {
* All the styles that are available by default from this plugin
*/
public static final ParticleStyle ARROWS = new ParticleStyleArrows();
public static final ParticleStyle BATMAN = new ParticleStyleBatman();
public static final ParticleStyle BEAM = new ParticleStyleBeam();
public static final ParticleStyle BLOCKBREAK = new ParticleStyleBlockBreak();
public static final ParticleStyle BLOCKEDIT = new ParticleStyleBlockEdit();
public static final ParticleStyle BLOCKPLACE = new ParticleStyleBlockPlace();
public static final ParticleStyle CHAINS = new ParticleStyleChains();
public static final ParticleStyle COMPANION = new ParticleStyleCompanion();
public static final ParticleStyle CUBE = new ParticleStyleCube();
public static final ParticleStyle FEET = new ParticleStyleFeet();
public static final ParticleStyle HALO = new ParticleStyleHalo();
public static final ParticleStyle HURT = new ParticleStyleHurt();
public static final ParticleStyle INVOCATION = new ParticleStyleInvocation();
public static final ParticleStyle MOVE = new ParticleStyleMove();
public static final ParticleStyle NONE = new ParticleStyleNone();
public static final ParticleStyle NORMAL = new ParticleStyleNormal();
public static final ParticleStyle ORBIT = new ParticleStyleOrbit();
public static final ParticleStyle OVERHEAD = new ParticleStyleOverhead();
public static final ParticleStyle POINT = new ParticleStylePoint();
public static final ParticleStyle QUADHELIX = new ParticleStyleQuadhelix();
public static final ParticleStyle RINGS = new ParticleStyleRings();
public static final ParticleStyle SPHERE = new ParticleStyleSphere();
public static final ParticleStyle SPIN = new ParticleStyleSpin();
public static final ParticleStyle SPIRAL = new ParticleStyleSpiral();
public static final ParticleStyle SWORDS = new ParticleStyleSwords();
public static final ParticleStyle THICK = new ParticleStyleThick();
public static final ParticleStyle VORTEX = new ParticleStyleVortex();
public static final ParticleStyle WINGS = new ParticleStyleWings();
/**
@ -41,26 +48,34 @@ public class DefaultStyles {
*/
public static void registerStyles() {
ParticleStyleManager.registerStyle(ARROWS);
ParticleStyleManager.registerStyle(BATMAN);
ParticleStyleManager.registerStyle(BEAM);
ParticleStyleManager.registerCustomHandledStyle(BLOCKBREAK);
ParticleStyleManager.registerCustomHandledStyle(BLOCKEDIT);
ParticleStyleManager.registerCustomHandledStyle(BLOCKPLACE);
ParticleStyleManager.registerStyle(CHAINS);
ParticleStyleManager.registerStyle(COMPANION);
ParticleStyleManager.registerStyle(CUBE);
ParticleStyleManager.registerStyle(FEET);
ParticleStyleManager.registerStyle(HALO);
ParticleStyleManager.registerCustomHandledStyle(HURT);
ParticleStyleManager.registerStyle(INVOCATION);
ParticleStyleManager.registerCustomHandledStyle(MOVE);
ParticleStyleManager.registerStyle(NONE);
ParticleStyleManager.registerStyle(NORMAL);
ParticleStyleManager.registerStyle(ORBIT);
ParticleStyleManager.registerStyle(OVERHEAD);
ParticleStyleManager.registerStyle(POINT);
ParticleStyleManager.registerStyle(QUADHELIX);
ParticleStyleManager.registerStyle(RINGS);
ParticleStyleManager.registerStyle(SPHERE);
ParticleStyleManager.registerStyle(SPIN);
ParticleStyleManager.registerStyle(SPIRAL);
ParticleStyleManager.registerCustomHandledStyle(SWORDS);
ParticleStyleManager.registerStyle(THICK);
ParticleStyleManager.registerStyle(VORTEX);
ParticleStyleManager.registerStyle(WINGS);
// Register their events
PluginManager manager = Bukkit.getPluginManager();
Plugin playerParticles = PlayerParticles.getPlugin();
manager.registerEvents((Listener) ARROWS, playerParticles);

View file

@ -11,7 +11,7 @@ import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntityShootBowEvent;
import com.esophose.playerparticles.PPlayer;
import com.esophose.playerparticles.particles.ParticlePair;
import com.esophose.playerparticles.styles.api.PParticle;
import com.esophose.playerparticles.styles.api.ParticleStyle;
@ -20,16 +20,16 @@ public class ParticleStyleArrows implements ParticleStyle, Listener {
private String[] arrowEntityNames = new String[] { "ARROW", "SPECTRAL_ARROW", "TIPPED_ARROW" };
private List<Arrow> arrows = new ArrayList<Arrow>();
public PParticle[] getParticles(PPlayer pplayer, Location location) {
public List<PParticle> getParticles(ParticlePair particle, Location location) {
List<PParticle> particles = new ArrayList<PParticle>();
for (Arrow arrow : arrows) {
if (((Player) arrow.getShooter()).getUniqueId() == pplayer.getUniqueId()) {
if (((Player) arrow.getShooter()).getUniqueId() == particle.getOwnerUniqueId()) {
particles.add(new PParticle(arrow.getLocation(), 0.05F, 0.05F, 0.05F, 0.0F));
}
}
return particles.toArray(new PParticle[particles.size()]);
return particles;
}
/**

View file

@ -0,0 +1,124 @@
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.particles.ParticlePair;
import com.esophose.playerparticles.styles.api.PParticle;
import com.esophose.playerparticles.styles.api.ParticleStyle;
import com.esophose.playerparticles.util.VectorUtils;
public class ParticleStyleBatman implements ParticleStyle {
private int step = 0;
public List<PParticle> getParticles(ParticlePair particle, Location location) {
List<PParticle> particles = new ArrayList<PParticle>();
if (step != 0) return particles;
// Segment 1
for (double x = -7; x <= -3; x += 0.05) {
double y = 3 * Math.sqrt(-Math.pow(x / 7, 2) + 1);
Vector segment = new Vector(x, y, 0).multiply(0.3);
VectorUtils.rotateAroundAxisY(segment, -Math.toRadians(location.getYaw()));
particles.add(new PParticle(location.clone().add(segment).add(0, 3, 0)));
}
for (double x = 3; x <= 7; x += 0.05) {
double y = 3 * Math.sqrt(-Math.pow(x / 7, 2) + 1);
Vector segment = new Vector(x, y, 0).multiply(0.3);
VectorUtils.rotateAroundAxisY(segment, -Math.toRadians(location.getYaw()));
particles.add(new PParticle(location.clone().add(segment).add(0, 3, 0)));
}
// Segment 2
for (double x = -7; x <= -4; x += 0.05) {
double y = -3 * Math.sqrt(-Math.pow(x / 7, 2) + 1);
Vector segment = new Vector(x, y, 0).multiply(0.3);
VectorUtils.rotateAroundAxisY(segment, -Math.toRadians(location.getYaw()));
particles.add(new PParticle(location.clone().add(segment).add(0, 3, 0)));
}
for (double x = 4; x <= 7; x += 0.05) {
double y = -3 * Math.sqrt(-Math.pow(x / 7, 2) + 1);
Vector segment = new Vector(x, y, 0).multiply(0.3);
VectorUtils.rotateAroundAxisY(segment, -Math.toRadians(location.getYaw()));
particles.add(new PParticle(location.clone().add(segment).add(0, 3, 0)));
}
// Segment 3
for (double x = -4; x <= 4; x += 0.125) {
double y = Math.abs(x / 2) - ((3 * Math.sqrt(33) - 7) / 112) * Math.pow(x, 2) + Math.sqrt(1 - Math.pow(Math.abs(Math.abs(x) - 2) - 1, 2)) - 3;
Vector segment = new Vector(x, y, 0).multiply(0.3);
VectorUtils.rotateAroundAxisY(segment, -Math.toRadians(location.getYaw()));
particles.add(new PParticle(location.clone().add(segment).add(0, 3, 0)));
}
// Segment 4
for (double x = -1; x <= -0.75; x += 0.025) {
double y = 9 - 8 * Math.abs(x);
Vector segment = new Vector(x, y, 0).multiply(0.3);
VectorUtils.rotateAroundAxisY(segment, -Math.toRadians(location.getYaw()));
particles.add(new PParticle(location.clone().add(segment).add(0, 3, 0)));
}
for (double x = 0.75; x <= 1; x += 0.025) {
double y = 9 - 8 * Math.abs(x);
Vector segment = new Vector(x, y, 0).multiply(0.3);
VectorUtils.rotateAroundAxisY(segment, -Math.toRadians(location.getYaw()));
particles.add(new PParticle(location.clone().add(segment).add(0, 3, 0)));
}
// Segment 5
for (double x = -0.75; x <= -0.5; x += 0.05) {
double y = 3 * Math.abs(x) + 0.75;
Vector segment = new Vector(x, y, 0).multiply(0.3);
VectorUtils.rotateAroundAxisY(segment, -Math.toRadians(location.getYaw()));
particles.add(new PParticle(location.clone().add(segment).add(0, 3, 0)));
}
for (double x = 0.5; x <= 0.75; x += 0.05) {
double y = 3 * Math.abs(x) + 0.75;
Vector segment = new Vector(x, y, 0).multiply(0.3);
VectorUtils.rotateAroundAxisY(segment, -Math.toRadians(location.getYaw()));
particles.add(new PParticle(location.clone().add(segment).add(0, 3, 0)));
}
// Segment 6
for (double x = -0.5; x <= 0.5; x += 0.2) {
double y = 2.25;
Vector segment = new Vector(x, y, 0).multiply(0.3);
VectorUtils.rotateAroundAxisY(segment, -Math.toRadians(location.getYaw()));
particles.add(new PParticle(location.clone().add(segment).add(0, 3, 0)));
}
// Segment 7
for (double x = -3; x <= -1; x += 0.02) {
double y = 1.5 - 0.5 * Math.abs(x) - ((6 * Math.sqrt(10)) / 14) * (Math.sqrt(3 - Math.pow(x, 2) + 2 * Math.abs(x)) - 2);
Vector segment = new Vector(x, y, 0).multiply(0.3);
VectorUtils.rotateAroundAxisY(segment, -Math.toRadians(location.getYaw()));
particles.add(new PParticle(location.clone().add(segment).add(0, 3, 0)));
}
for (double x = 1; x <= 3; x += 0.02) {
double y = 1.5 - 0.5 * Math.abs(x) - ((6 * Math.sqrt(10)) / 14) * (Math.sqrt(3 - Math.pow(x, 2) + 2 * Math.abs(x)) - 2);
Vector segment = new Vector(x, y, 0).multiply(0.3);
VectorUtils.rotateAroundAxisY(segment, -Math.toRadians(location.getYaw()));
particles.add(new PParticle(location.clone().add(segment).add(0, 3, 0)));
}
return particles;
}
public void updateTimers() {
step = (step + 1) % 20; // Only spawn once per second
}
public String getName() {
return "batman";
}
public boolean canBeFixed() {
return true;
}
}

View file

@ -1,27 +1,41 @@
package com.esophose.playerparticles.styles;
import java.util.ArrayList;
import java.util.List;
import org.bukkit.Location;
import com.esophose.playerparticles.PPlayer;
import com.esophose.playerparticles.particles.ParticlePair;
import com.esophose.playerparticles.styles.api.PParticle;
import com.esophose.playerparticles.styles.api.ParticleStyle;
public class ParticleStyleBeam implements ParticleStyle {
private float step = 0;
private static double[] cos, sin;
private static final int points = 16;
private int step = 0;
private boolean reversed = false;
static {
cos = new double[points];
sin = new double[points];
int i = 0;
for (double n = 0; n < Math.PI * 2; n += Math.PI * 2 / points) {
cos[i] = Math.cos(n);
sin[i] = Math.sin(n);
i++;
}
}
public PParticle[] getParticles(PPlayer pplayer, Location location) {
int points = 16;
public List<PParticle> getParticles(ParticlePair particle, Location location) {
double radius = 1;
double slice = 2 * Math.PI / points;
PParticle[] particles = new PParticle[points];
List<PParticle> particles = new ArrayList<PParticle>();
for (int i = 0; i < points; i++) {
double angle = slice * i;
double newX = location.getX() + radius * Math.cos(angle);
double newY = location.getY() + (step / 10) - 1;
double newZ = location.getZ() + radius * Math.sin(angle);
particles[i] = new PParticle(new Location(location.getWorld(), newX, newY, newZ));
double newX = location.getX() + radius * cos[i];
double newY = location.getY() + (step / 10D) - 1;
double newZ = location.getZ() + radius * sin[i];
particles.add(new PParticle(new Location(location.getWorld(), newX, newY, newZ)));
}
return particles;
}

View file

@ -10,26 +10,28 @@ import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockBreakEvent;
import com.esophose.playerparticles.PPlayer;
import com.esophose.playerparticles.manager.PPlayerDataManager;
import com.esophose.playerparticles.manager.DataManager;
import com.esophose.playerparticles.manager.ParticleManager;
import com.esophose.playerparticles.manager.PermissionManager;
import com.esophose.playerparticles.particles.PPlayer;
import com.esophose.playerparticles.particles.ParticlePair;
import com.esophose.playerparticles.styles.api.PParticle;
import com.esophose.playerparticles.styles.api.ParticleStyle;
public class ParticleStyleBlockBreak implements ParticleStyle, Listener {
public PParticle[] getParticles(PPlayer pplayer, Location location) {
public List<PParticle> getParticles(ParticlePair particle, Location location) {
List<PParticle> particles = new ArrayList<PParticle>();
location.add(0.5, 0.5, 0.5); // Center around the block
for (int i = 0; i < 15; i++)
particles.add(new PParticle(location.clone().add(0.5, 0.5, 0.5), 0.5F, 0.5F, 0.5F, 0.05F));
for (int i = 0; i < 15; i++)
particles.add(new PParticle(location, 0.5F, 0.5F, 0.5F, 0.05F));
return particles.toArray(new PParticle[particles.size()]);
return particles;
}
public void updateTimers() {
}
public String getName() {
@ -39,14 +41,16 @@ public class ParticleStyleBlockBreak implements ParticleStyle, Listener {
public boolean canBeFixed() {
return false;
}
@EventHandler(priority = EventPriority.MONITOR)
public void onBlockBreak(BlockBreakEvent event) {
Player player = event.getPlayer();
PPlayer pplayer = PPlayerDataManager.getInstance().getPPlayer(player.getUniqueId());
if (pplayer != null && pplayer.getParticleStyle() == DefaultStyles.BLOCKBREAK && PermissionManager.hasStylePermission(player, DefaultStyles.BLOCKBREAK)) {
Location loc = event.getBlock().getLocation();
ParticleManager.displayParticles(pplayer, DefaultStyles.BLOCKBREAK.getParticles(pplayer, loc));
PPlayer pplayer = DataManager.getPPlayer(player.getUniqueId());
if (pplayer != null) {
for (ParticlePair particle : pplayer.getActiveParticlesForStyle(DefaultStyles.BLOCKBREAK)) {
Location loc = event.getBlock().getLocation().clone();
ParticleManager.displayParticles(particle, DefaultStyles.BLOCKBREAK.getParticles(particle, loc));
}
}
}

View file

@ -1,5 +1,8 @@
package com.esophose.playerparticles.styles;
import java.util.ArrayList;
import java.util.List;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
@ -8,21 +11,21 @@ import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.event.block.BlockPlaceEvent;
import com.esophose.playerparticles.PPlayer;
import com.esophose.playerparticles.manager.PPlayerDataManager;
import com.esophose.playerparticles.manager.DataManager;
import com.esophose.playerparticles.manager.ParticleManager;
import com.esophose.playerparticles.manager.PermissionManager;
import com.esophose.playerparticles.particles.PPlayer;
import com.esophose.playerparticles.particles.ParticlePair;
import com.esophose.playerparticles.styles.api.PParticle;
import com.esophose.playerparticles.styles.api.ParticleStyle;
public class ParticleStyleBlockEdit implements ParticleStyle, Listener {
public PParticle[] getParticles(PPlayer pplayer, Location location) {
return new PParticle[0]; // Particles are taken from DefaultStyles.BLOCKPLACE or DefaultStyles.BLOCKBREAK
public List<PParticle> getParticles(ParticlePair particle, Location location) {
return new ArrayList<PParticle>(); // Particles are taken from DefaultStyles.BLOCKPLACE or DefaultStyles.BLOCKBREAK
}
public void updateTimers() {
}
public String getName() {
@ -32,24 +35,28 @@ public class ParticleStyleBlockEdit implements ParticleStyle, Listener {
public boolean canBeFixed() {
return false;
}
@EventHandler(priority = EventPriority.MONITOR)
public void onBlockBreak(BlockBreakEvent event) {
Player player = event.getPlayer();
PPlayer pplayer = PPlayerDataManager.getInstance().getPPlayer(player.getUniqueId());
if (pplayer != null && pplayer.getParticleStyle() == DefaultStyles.BLOCKEDIT && PermissionManager.hasStylePermission(player, DefaultStyles.BLOCKEDIT)) {
Location loc = event.getBlock().getLocation();
ParticleManager.displayParticles(pplayer, DefaultStyles.BLOCKBREAK.getParticles(pplayer, loc));
PPlayer pplayer = DataManager.getPPlayer(player.getUniqueId());
if (pplayer != null) {
for (ParticlePair particle : pplayer.getActiveParticlesForStyle(DefaultStyles.BLOCKEDIT)) {
Location loc = event.getBlock().getLocation();
ParticleManager.displayParticles(particle, DefaultStyles.BLOCKBREAK.getParticles(particle, loc));
}
}
}
@EventHandler(priority = EventPriority.MONITOR)
public void onBlockPlace(BlockPlaceEvent event) {
Player player = event.getPlayer();
PPlayer pplayer = PPlayerDataManager.getInstance().getPPlayer(player.getUniqueId());
if (pplayer != null && pplayer.getParticleStyle() == DefaultStyles.BLOCKEDIT && PermissionManager.hasStylePermission(player, DefaultStyles.BLOCKEDIT)) {
Location loc = event.getBlockPlaced().getLocation();
ParticleManager.displayParticles(pplayer, DefaultStyles.BLOCKPLACE.getParticles(pplayer, loc));
PPlayer pplayer = DataManager.getPPlayer(player.getUniqueId());
if (pplayer != null) {
for (ParticlePair particle : pplayer.getActiveParticlesForStyle(DefaultStyles.BLOCKEDIT)) {
Location loc = event.getBlock().getLocation().clone();
ParticleManager.displayParticles(particle, DefaultStyles.BLOCKPLACE.getParticles(particle, loc));
}
}
}

View file

@ -10,22 +10,24 @@ import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockPlaceEvent;
import com.esophose.playerparticles.PPlayer;
import com.esophose.playerparticles.manager.PPlayerDataManager;
import com.esophose.playerparticles.manager.DataManager;
import com.esophose.playerparticles.manager.ParticleManager;
import com.esophose.playerparticles.manager.PermissionManager;
import com.esophose.playerparticles.particles.PPlayer;
import com.esophose.playerparticles.particles.ParticlePair;
import com.esophose.playerparticles.styles.api.PParticle;
import com.esophose.playerparticles.styles.api.ParticleStyle;
public class ParticleStyleBlockPlace implements ParticleStyle, Listener {
public PParticle[] getParticles(PPlayer pplayer, Location location) {
public List<PParticle> getParticles(ParticlePair particle, Location location) {
List<PParticle> particles = new ArrayList<PParticle>();
location.add(0.5, 0.5, 0.5); // Center around the block
for (int i = 0; i < 15; i++)
particles.add(new PParticle(location.clone().add(0.5, 0.5, 0.5), 0.75F, 0.75F, 0.75F, 0.05F));
for (int i = 0; i < 15; i++)
particles.add(new PParticle(location, 0.75F, 0.75F, 0.75F, 0.05F));
return particles.toArray(new PParticle[particles.size()]);
return particles;
}
public void updateTimers() {
@ -43,10 +45,12 @@ public class ParticleStyleBlockPlace implements ParticleStyle, Listener {
@EventHandler(priority = EventPriority.MONITOR)
public void onBlockPlace(BlockPlaceEvent event) {
Player player = event.getPlayer();
PPlayer pplayer = PPlayerDataManager.getInstance().getPPlayer(player.getUniqueId());
if (pplayer != null && pplayer.getParticleStyle() == DefaultStyles.BLOCKPLACE && PermissionManager.hasStylePermission(player, DefaultStyles.BLOCKPLACE)) {
Location loc = event.getBlockPlaced().getLocation();
ParticleManager.displayParticles(pplayer, DefaultStyles.BLOCKPLACE.getParticles(pplayer, loc));
PPlayer pplayer = DataManager.getPPlayer(player.getUniqueId());
if (pplayer != null) {
for (ParticlePair particle : pplayer.getActiveParticlesForStyle(DefaultStyles.BLOCKPLACE)) {
Location loc = event.getBlock().getLocation().clone();
ParticleManager.displayParticles(particle, DefaultStyles.BLOCKPLACE.getParticles(particle, loc));
}
}
}

View file

@ -0,0 +1,39 @@
package com.esophose.playerparticles.styles;
import java.util.ArrayList;
import java.util.List;
import org.bukkit.Location;
import com.esophose.playerparticles.particles.ParticlePair;
import com.esophose.playerparticles.styles.api.PParticle;
import com.esophose.playerparticles.styles.api.ParticleStyle;
public class ParticleStyleChains implements ParticleStyle {
public List<PParticle> getParticles(ParticlePair particle, Location location) {
List<PParticle> particles = new ArrayList<PParticle>();
for (double n = -0.2; n < 0.6; n += 0.1) {
particles.add(new PParticle(location.clone().add(1 - n, n - 1.1, 1 - n)));
particles.add(new PParticle(location.clone().add(1 - n, n - 1.1, -1 + n)));
particles.add(new PParticle(location.clone().add(-1 + n, n - 1.1, 1 - n)));
particles.add(new PParticle(location.clone().add(-1 + n, n - 1.1, -1 + n)));
}
return particles;
}
public void updateTimers() {
}
public String getName() {
return "chains";
}
public boolean canBeFixed() {
return true;
}
}

View file

@ -0,0 +1,77 @@
/**
* The MIT License (MIT)
*
* Copyright (c) 2014 Slikey
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
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.particles.ParticlePair;
import com.esophose.playerparticles.styles.api.PParticle;
import com.esophose.playerparticles.styles.api.ParticleStyle;
public class ParticleStyleCompanion implements ParticleStyle {
private int numParticles = 150;
private int particlesPerIteration = 5;
private double size = 1.25;
private double xFactor = 1.0, yFactor = 1.5, zFactor = 1.0;
private double xOffset = 0.0, yOffset = -0.75, zOffset = 0.0;
private int step = 0;
public List<PParticle> getParticles(ParticlePair particle, Location location) {
List<PParticle> particles = new ArrayList<PParticle>();
Vector vector = new Vector();
double t = (Math.PI / numParticles) * step;
double r = Math.sin(t) * size;
double s = 2 * Math.PI * t;
vector.setX(xFactor * r * Math.cos(s) + xOffset);
vector.setZ(zFactor * r * Math.sin(s) + zOffset);
vector.setY(yFactor * size * Math.cos(t) + yOffset);
for (int i = 0; i < particlesPerIteration; i++) {
particles.add(new PParticle(location.clone().subtract(vector)));
}
return particles;
}
public void updateTimers() {
step++;
}
public String getName() {
return "companion";
}
public boolean canBeFixed() {
return true;
}
}

View file

@ -29,7 +29,7 @@ import java.util.List;
import org.bukkit.Location;
import org.bukkit.util.Vector;
import com.esophose.playerparticles.PPlayer;
import com.esophose.playerparticles.particles.ParticlePair;
import com.esophose.playerparticles.styles.api.PParticle;
import com.esophose.playerparticles.styles.api.ParticleStyle;
import com.esophose.playerparticles.util.VectorUtils;
@ -41,7 +41,7 @@ import com.esophose.playerparticles.util.VectorUtils;
*/
public class ParticleStyleCube implements ParticleStyle {
private float edgeLength = 2;
private double edgeLength = 2;
private double angularVelocityX = (Math.PI / 200) / 5;
private double angularVelocityY = (Math.PI / 170) / 5;
private double angularVelocityZ = (Math.PI / 155) / 5;
@ -49,7 +49,7 @@ public class ParticleStyleCube implements ParticleStyle {
private int step = 0;
private boolean skipNextStep = false; // Only spawn every 2 ticks
public PParticle[] getParticles(PPlayer pplayer, Location location) {
public List<PParticle> getParticles(ParticlePair particle, Location location) {
List<PParticle> pparticles = new ArrayList<PParticle>();
if (!skipNextStep) {
@ -57,7 +57,7 @@ public class ParticleStyleCube implements ParticleStyle {
xRotation = step * angularVelocityX;
yRotation = step * angularVelocityY;
zRotation = step * angularVelocityZ;
float a = edgeLength / 2;
double a = edgeLength / 2;
double angleX, angleY;
Vector v = new Vector();
for (int i = 0; i < 4; i++) {
@ -83,7 +83,7 @@ public class ParticleStyleCube implements ParticleStyle {
}
}
return pparticles.toArray(new PParticle[pparticles.size()]);
return pparticles;
}
public void updateTimers() {

View file

@ -1,15 +1,20 @@
package com.esophose.playerparticles.styles;
import java.util.ArrayList;
import java.util.List;
import org.bukkit.Location;
import com.esophose.playerparticles.PPlayer;
import com.esophose.playerparticles.particles.ParticlePair;
import com.esophose.playerparticles.styles.api.PParticle;
import com.esophose.playerparticles.styles.api.ParticleStyle;
public class ParticleStyleFeet implements ParticleStyle {
public PParticle[] getParticles(PPlayer pplayer, Location location) {
return new PParticle[] { new PParticle(location.subtract(0, 0.95, 0), 0.4F, 0.0F, 0.4F, 0.0F) };
public List<PParticle> getParticles(ParticlePair particle, Location location) {
List<PParticle> particles = new ArrayList<PParticle>();
particles.add(new PParticle(location.clone().subtract(0, 0.95, 0), 0.4F, 0.0F, 0.4F, 0.0F));
return particles;
}
public void updateTimers() {

View file

@ -1,27 +1,43 @@
package com.esophose.playerparticles.styles;
import java.util.ArrayList;
import java.util.List;
import org.bukkit.Location;
import com.esophose.playerparticles.PPlayer;
import com.esophose.playerparticles.particles.ParticlePair;
import com.esophose.playerparticles.styles.api.PParticle;
import com.esophose.playerparticles.styles.api.ParticleStyle;
public class ParticleStyleHalo implements ParticleStyle {
private float step = 0;
private static double[] cos, sin;
private static final int points = 16;
private int step = 0;
static {
cos = new double[points];
sin = new double[points];
int i = 0;
for (double n = 0; n < Math.PI * 2; n += Math.PI * 2 / points) {
cos[i] = Math.cos(n);
sin[i] = Math.sin(n);
i++;
}
}
public List<PParticle> getParticles(ParticlePair particle, Location location) {
if (step % 2 == 0) return new ArrayList<PParticle>();
public PParticle[] getParticles(PPlayer pplayer, Location location) {
if (step % 2 == 0) return new PParticle[0];
int points = 16;
double radius = .65;
double slice = 2 * Math.PI / points;
PParticle[] particles = new PParticle[points];
List<PParticle> particles = new ArrayList<PParticle>();
for (int i = 0; i < points; i++) {
double angle = slice * i;
double newX = location.getX() + radius * Math.cos(angle);
double newY = location.getY() + 1.5;
double newZ = location.getZ() + radius * Math.sin(angle);
particles[i] = new PParticle(new Location(location.getWorld(), newX, newY, newZ));
double dx = radius * cos[i];
double dy = 1.5;
double dz = radius * sin[i];
particles.add(new PParticle(location.clone().add(dx, dy, dz)));
}
return particles;
}

View file

@ -1,5 +1,8 @@
package com.esophose.playerparticles.styles;
import java.util.ArrayList;
import java.util.List;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
@ -7,29 +10,29 @@ import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntityDamageEvent;
import com.esophose.playerparticles.PPlayer;
import com.esophose.playerparticles.manager.PPlayerDataManager;
import com.esophose.playerparticles.manager.DataManager;
import com.esophose.playerparticles.manager.ParticleManager;
import com.esophose.playerparticles.manager.PermissionManager;
import com.esophose.playerparticles.particles.PPlayer;
import com.esophose.playerparticles.particles.ParticlePair;
import com.esophose.playerparticles.styles.api.PParticle;
import com.esophose.playerparticles.styles.api.ParticleStyle;
public class ParticleStyleHurt implements ParticleStyle, Listener {
public PParticle[] getParticles(PPlayer pplayer, Location location) {
PParticle[] baseParticles = DefaultStyles.THICK.getParticles(pplayer, location);
public List<PParticle> getParticles(ParticlePair particle, Location location) {
List<PParticle> baseParticles = DefaultStyles.THICK.getParticles(particle, location);
int multiplyingFactor = 3; // Uses the same logic as ParticleStyleThick except multiplies the resulting particles by 3x
PParticle[] particles = new PParticle[baseParticles.length * multiplyingFactor];
for (int i = 0; i < baseParticles.length * multiplyingFactor; i++) {
particles[i] = baseParticles[i % baseParticles.length];
List<PParticle> particles = new ArrayList<PParticle>();
for (int i = 0; i < baseParticles.size() * multiplyingFactor; i++) {
particles.add(baseParticles.get(i % baseParticles.size()));
}
return particles;
}
public void updateTimers() {
}
public String getName() {
@ -39,17 +42,19 @@ public class ParticleStyleHurt implements ParticleStyle, Listener {
public boolean canBeFixed() {
return false;
}
@EventHandler(priority = EventPriority.MONITOR)
public void onEntityDamage(EntityDamageEvent event) {
if (event.getEntity() instanceof Player) {
Player player = (Player) event.getEntity();
PPlayer pplayer = PPlayerDataManager.getInstance().getPPlayer(player.getUniqueId());
if (pplayer != null && pplayer.getParticleStyle() == DefaultStyles.HURT && PermissionManager.hasStylePermission(player, DefaultStyles.HURT)) {
Location loc = player.getLocation().clone().add(0, 1, 0);
ParticleManager.displayParticles(pplayer, DefaultStyles.HURT.getParticles(pplayer, loc));
PPlayer pplayer = DataManager.getPPlayer(player.getUniqueId());
if (pplayer != null) {
for (ParticlePair particle : pplayer.getActiveParticlesForStyle(DefaultStyles.HURT)) {
Location loc = player.getLocation().clone().add(0, 1, 0);
ParticleManager.displayParticles(particle, DefaultStyles.HURT.getParticles(particle, loc));
}
}
}
}
}
}

View file

@ -0,0 +1,102 @@
package com.esophose.playerparticles.styles;
import java.util.ArrayList;
import java.util.List;
import org.bukkit.Location;
import com.esophose.playerparticles.particles.ParticleEffect;
import com.esophose.playerparticles.particles.ParticlePair;
import com.esophose.playerparticles.styles.api.PParticle;
import com.esophose.playerparticles.styles.api.ParticleStyle;
public class ParticleStyleInvocation implements ParticleStyle {
private int points = 6;
private double radius = 3.5;
private double step = 0;
private int circleStep = 0;
private int numSteps = 120;
public List<PParticle> getParticles(ParticlePair particle, Location location) {
List<PParticle> particles = new ArrayList<PParticle>();
double speed = getSpeedByEffect(particle.getEffect());
// Circle around everything, spawn less often
if (circleStep % 5 == 0) {
for (int i = 0; i < numSteps; i++) {
double dx = Math.cos(Math.PI * 2 * ((double)i / numSteps)) * radius;
double dy = -0.9;
double dz = Math.sin(Math.PI * 2 * ((double)i / numSteps)) * radius;
particles.add(new PParticle(location.clone().add(dx, dy, dz)));
}
}
// Orbit going clockwise
for (int i = 0; i < points; i++) {
double dx = Math.cos(step + (Math.PI * 2 * ((double)i / points))) * radius;
double dy = -0.9;
double dz = Math.sin(step + (Math.PI * 2 * ((double)i / points))) * radius;
double angle = Math.atan2(dz, dx);
double xAng = -Math.cos(angle);
double zAng = -Math.sin(angle);
particles.add(new PParticle(location.clone().add(dx, dy, dz), xAng, 0, zAng, speed, true));
}
// Orbit going counter-clockwise
for (int i = 0; i > -points; i--) {
double dx = Math.cos(-step + (Math.PI * 2 * ((double)i / points))) * radius;
double dy = -0.9;
double dz = Math.sin(-step + (Math.PI * 2 * ((double)i / points))) * radius;
double angle = Math.atan2(dz, dx);
double xAng = -Math.cos(angle);
double zAng = -Math.sin(angle);
particles.add(new PParticle(location.clone().add(dx, dy, dz), xAng, 0, zAng, speed, true));
}
return particles;
}
private double getSpeedByEffect(ParticleEffect effect) {
switch (effect) {
case CRIT:
case DAMAGE_INDICATOR:
case ENCHANTED_HIT:
return 2;
case DRAGON_BREATH:
return 0.01;
case ENCHANT:
case NAUTILUS:
case PORTAL:
return radius * 2;
case END_ROD:
case SMOKE:
case SQUID_INK:
return 0.3;
case FIREWORK:
case SPIT:
case SPLASH:
return 0.5;
case POOF:
return 0.4;
case TOTEM_OF_UNDYING:
return 1.25;
default:
return 0.2; // Flame
}
}
public void updateTimers() {
step = (step + Math.PI * 2 / numSteps) % numSteps;
circleStep = (circleStep + 1) % numSteps;
}
public String getName() {
return "invocation";
}
public boolean canBeFixed() {
return true;
}
}

View file

@ -1,26 +1,28 @@
package com.esophose.playerparticles.styles;
import java.util.List;
import org.bukkit.Location;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerMoveEvent;
import com.esophose.playerparticles.PPlayer;
import com.esophose.playerparticles.manager.PPlayerDataManager;
import com.esophose.playerparticles.manager.DataManager;
import com.esophose.playerparticles.manager.ParticleManager;
import com.esophose.playerparticles.manager.PermissionManager;
import com.esophose.playerparticles.particles.PPlayer;
import com.esophose.playerparticles.particles.ParticlePair;
import com.esophose.playerparticles.styles.api.PParticle;
import com.esophose.playerparticles.styles.api.ParticleStyle;
public class ParticleStyleMove implements ParticleStyle, Listener {
public PParticle[] getParticles(PPlayer pplayer, Location location) {
return DefaultStyles.NONE.getParticles(pplayer, location);
public List<PParticle> getParticles(ParticlePair particle, Location location) {
return DefaultStyles.NORMAL.getParticles(particle, location);
}
public void updateTimers() {
}
public String getName() {
@ -30,15 +32,15 @@ public class ParticleStyleMove implements ParticleStyle, Listener {
public boolean canBeFixed() {
return false;
}
@EventHandler(priority = EventPriority.MONITOR)
public void onPlayerMove(PlayerMoveEvent e) {
PPlayer pplayer = PPlayerDataManager.getInstance().getPPlayer(e.getPlayer().getUniqueId());
if (pplayer != null && pplayer.getParticleStyle() == DefaultStyles.MOVE) {
if (PermissionManager.hasStylePermission(e.getPlayer(), DefaultStyles.MOVE)) {
Location loc = e.getPlayer().getLocation();
PPlayer pplayer = DataManager.getPPlayer(e.getPlayer().getUniqueId());
if (pplayer != null) {
for (ParticlePair particle : pplayer.getActiveParticlesForStyle(DefaultStyles.MOVE)) {
Location loc = e.getPlayer().getLocation().clone();
loc.setY(loc.getY() + 0.05);
ParticleManager.displayParticles(pplayer, DefaultStyles.MOVE.getParticles(pplayer, loc));
ParticleManager.displayParticles(particle, DefaultStyles.MOVE.getParticles(particle, loc));
}
}
}

View file

@ -1,124 +0,0 @@
package com.esophose.playerparticles.styles;
import org.bukkit.Location;
import com.esophose.playerparticles.PPlayer;
import com.esophose.playerparticles.particles.ParticleEffect;
import com.esophose.playerparticles.styles.api.PParticle;
import com.esophose.playerparticles.styles.api.ParticleStyle;
public class ParticleStyleNone implements ParticleStyle {
public PParticle[] getParticles(PPlayer pplayer, Location location) {
ParticleEffect particleEffect = pplayer.getParticleEffect();
if (particleEffect.equals(ParticleEffect.ANGRY_VILLAGER)) {
return new PParticle[] { new PParticle(location, 0.6F, 0.6F, 0.6F, 0.0F) };
} else if (particleEffect.equals(ParticleEffect.BUBBLE)) {
return new PParticle[] { new PParticle(location, 0.4F, 0.4F, 0.4F, 0.0F) };
} else if (particleEffect.equals(ParticleEffect.CLOUD)) {
return new PParticle[] { new PParticle(location, 0.4F, 0.4F, 0.4F, 0.0F) };
} else if (particleEffect.equals(ParticleEffect.CRIT)) {
return new PParticle[] { new PParticle(location, 0.4F, 0.4F, 0.4F, 0.0F) };
} else if (particleEffect.equals(ParticleEffect.UNDERWATER)) {
PParticle[] particles = new PParticle[5];
for (int i = 0; i < 5; i++)
particles[i] = new PParticle(location, 0.5F, 0.5F, 0.5F, 0.0F);
return particles;
} else if (particleEffect.equals(ParticleEffect.DRIPPING_LAVA)) {
return new PParticle[] { new PParticle(location, 0.6F, 0.6F, 0.6F, 0.0F) };
} else if (particleEffect.equals(ParticleEffect.DRIPPING_LAVA)) {
return new PParticle[] { new PParticle(location, 0.6F, 0.6F, 0.6F, 0.0F) };
} else if (particleEffect.equals(ParticleEffect.ENCHANT)) {
return new PParticle[] { new PParticle(location, 0.6F, 0.6F, 0.6F, 0.05F) };
} else if (particleEffect.equals(ParticleEffect.POOF)) {
return new PParticle[] { new PParticle(location, 0.4F, 0.4F, 0.4F, 0.0F) };
} else if (particleEffect.equals(ParticleEffect.FIREWORK)) {
return new PParticle[] { new PParticle(location, 0.4F, 0.4F, 0.4F, 0.0F) };
} else if (particleEffect.equals(ParticleEffect.FLAME)) {
return new PParticle[] { new PParticle(location, 0.1F, 0.1F, 0.1F, 0.05F) };
} else if (particleEffect.equals(ParticleEffect.FOOTSTEP)) {
return new PParticle[] { new PParticle(location, 0.4F, 0.4F, 0.4F, 0.0F) };
} else if (particleEffect.equals(ParticleEffect.HAPPY_VILLAGER)) {
return new PParticle[] { new PParticle(location, 0.5F, 0.5F, 0.5F, 0.0F) };
} else if (particleEffect.equals(ParticleEffect.HEART)) {
return new PParticle[] { new PParticle(location, 0.6F, 0.6F, 0.6F, 0.0F) };
} else if (particleEffect.equals(ParticleEffect.EXPLOSION_EMITTER)) {
return new PParticle[] { new PParticle(location, 0.4F, 0.4F, 0.4F, 0.0F) };
} else if (particleEffect.equals(ParticleEffect.INSTANT_EFFECT)) {
return new PParticle[] { new PParticle(location, 0.4F, 0.4F, 0.4F, 0.0F) };
} else if (particleEffect.equals(ParticleEffect.EXPLOSION)) {
return new PParticle[] { new PParticle(location, 0.4F, 0.4F, 0.4F, 0.0F) };
} else if (particleEffect.equals(ParticleEffect.LARGE_SMOKE)) {
return new PParticle[] { new PParticle(location, 0.4F, 0.4F, 0.4F, 0.0F) };
} else if (particleEffect.equals(ParticleEffect.LAVA)) {
return new PParticle[] { new PParticle(location, 0.4F, 0.4F, 0.4F, 0.0F) };
} else if (particleEffect.equals(ParticleEffect.ENCHANTED_HIT)) {
return new PParticle[] { new PParticle(location, 0.4F, 0.4F, 0.4F, 0.0F) };
} else if (particleEffect.equals(ParticleEffect.ENTITY_EFFECT)) {
return new PParticle[] { new PParticle(location, 0.4F, 0.4F, 0.4F, 0.0F) };
} else if (particleEffect.equals(ParticleEffect.AMBIENT_ENTITY_EFFECT)) {
return new PParticle[] { new PParticle(location, 0.4F, 0.4F, 0.4F, 0.0F) };
} else if (particleEffect.equals(ParticleEffect.NOTE)) {
return new PParticle[] { new PParticle(location, 0.6F, 0.6F, 0.6F, 0.0F) };
} else if (particleEffect.equals(ParticleEffect.PORTAL)) {
return new PParticle[] { new PParticle(location, 0.5F, 0.5F, 0.5F, 0.05F) };
} else if (particleEffect.equals(ParticleEffect.DUST)) {
return new PParticle[] { new PParticle(location, 0.5F, 0.5F, 0.5F, 0.0F) };
} else if (particleEffect.equals(ParticleEffect.ITEM_SLIME)) {
return new PParticle[] { new PParticle(location, 0.4F, 0.4F, 0.4F, 0.0F) };
} else if (particleEffect.equals(ParticleEffect.SMOKE)) {
return new PParticle[] { new PParticle(location, 0.4F, 0.4F, 0.4F, 0.0F) };
} else if (particleEffect.equals(ParticleEffect.ITEM_SNOWBALL)) {
return new PParticle[] { new PParticle(location, 0.4F, 0.4F, 0.4F, 0.0F) };
} else if (particleEffect.equals(ParticleEffect.SPELL)) {
return new PParticle[] { new PParticle(location, 0.4F, 0.4F, 0.4F, 0.0F) };
} else if (particleEffect.equals(ParticleEffect.UNDERWATER)) {
PParticle[] particles = new PParticle[3];
for (int i = 0; i < 3; i++)
particles[i] = new PParticle(location, 0.4F, 0.4F, 0.4F, 0.0F);
return particles;
} else if (particleEffect.equals(ParticleEffect.WITCH)) {
return new PParticle[] { new PParticle(location, 0.4F, 0.4F, 0.4F, 0.0F) };
} else if (particleEffect.equals(ParticleEffect.BARRIER)) {
return new PParticle[] { new PParticle(location, 1.2F, 1.2F, 1.2F, 0.0F) };
} else if (particleEffect.equals(ParticleEffect.SPLASH)) {
return new PParticle[] { new PParticle(location, 0.8F, 0.8F, 0.8F, 0.0F) };
} else if (particleEffect.equals(ParticleEffect.DRAGON_BREATH)) {
return new PParticle[] { new PParticle(location, 0.4F, 0.4F, 0.4F, 0.0F) };
} else if (particleEffect.equals(ParticleEffect.END_ROD)) {
return new PParticle[] { new PParticle(location, 0.4F, 0.4F, 0.4F, 0.0F) };
} else if (particleEffect.equals(ParticleEffect.DAMAGE_INDICATOR)) {
return new PParticle[] { new PParticle(location, 0.4F, 0.4F, 0.4F, 0.0F) };
} else if (particleEffect.equals(ParticleEffect.SWEEP_ATTACK)) {
return new PParticle[] { new PParticle(location, 0.4F, 0.4F, 0.4F, 0.0F) };
} else if (particleEffect.equals(ParticleEffect.BLOCK)) {
return new PParticle[] { new PParticle(location, 0.6F, 0.6F, 0.6F, 0.0F) };
} else if (particleEffect.equals(ParticleEffect.ITEM)) {
return new PParticle[] { new PParticle(location, 0.6F, 0.6F, 0.6F, 0.0F) };
} else if (particleEffect.equals(ParticleEffect.FALLING_DUST)) {
PParticle[] particles = new PParticle[2];
for (int i = 0; i < 2; i++)
particles[i] = new PParticle(location.add(0, 0.75, 0), 0.6F, 0.4F, 0.6F, 0.0F);
return particles;
} else if (particleEffect.equals(ParticleEffect.TOTEM_OF_UNDYING)) {
return new PParticle[] { new PParticle(location, 0.6F, 0.6F, 0.6F, 0.0F) };
} else if (particleEffect.equals(ParticleEffect.SPIT)) {
return new PParticle[] { new PParticle(location, 0.6F, 0.6F, 0.6F, 0.0F) };
} else {
return new PParticle[] { new PParticle(location, 0.4F, 0.4F, 0.4F, 0.0F) };
}
}
public void updateTimers() {
}
public String getName() {
return "none";
}
public boolean canBeFixed() {
return true;
}
}

View file

@ -0,0 +1,142 @@
package com.esophose.playerparticles.styles;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.bukkit.Location;
import com.esophose.playerparticles.particles.ParticleEffect;
import com.esophose.playerparticles.particles.ParticlePair;
import com.esophose.playerparticles.styles.api.PParticle;
import com.esophose.playerparticles.styles.api.ParticleStyle;
public class ParticleStyleNormal implements ParticleStyle {
public List<PParticle> getParticles(ParticlePair particle, Location location) {
ParticleEffect particleEffect = particle.getEffect();
List<PParticle> particles = new ArrayList<PParticle>();
switch (particleEffect) {
case AMBIENT_ENTITY_EFFECT:
return Collections.singletonList(new PParticle(location, 0.6, 0.6, 0.6, 0.0));
case ANGRY_VILLAGER:
return Collections.singletonList(new PParticle(location, 0.6, 0.6, 0.6, 0.0));
case BARRIER:
return Collections.singletonList(new PParticle(location, 0.6, 0.6, 0.6, 0.0));
case BLOCK:
return Collections.singletonList(new PParticle(location, 0.6, 0.6, 0.6, 0.0));
case BUBBLE:
return Collections.singletonList(new PParticle(location, 0.4, 0.4, 0.4, 0.0));
case BUBBLE_COLUMN_UP:
return Collections.singletonList(new PParticle(location, 0.4, 0.4, 0.4, 0.0));
case BUBBLE_POP:
return Collections.singletonList(new PParticle(location, 0.4, 0.4, 0.4, 0.0));
case CLOUD:
return Collections.singletonList(new PParticle(location, 0.0, 0.0, 0.0, 0.0));
case CRIT:
return Collections.singletonList(new PParticle(location, 0.4, 0.4, 0.4, 0.0));
case CURRENT_DOWN:
return Collections.singletonList(new PParticle(location, 0.4, 0.4, 0.4, 0.0));
case DAMAGE_INDICATOR:
return Collections.singletonList(new PParticle(location, 0.4, 0.4, 0.4, 0.0));
case DOLPHIN:
return Collections.singletonList(new PParticle(location, 0.4, 0.4, 0.4, 0.0));
case DRAGON_BREATH:
return Collections.singletonList(new PParticle(location, 0.4, 0.4, 0.4, 0.0));
case DRIPPING_LAVA:
return Collections.singletonList(new PParticle(location, 0.6, 0.6, 0.6, 0.0));
case DRIPPING_WATER:
return Collections.singletonList(new PParticle(location, 0.6, 0.6, 0.6, 0.0));
case DUST:
return Collections.singletonList(new PParticle(location, 0.5, 0.5, 0.5, 0.0));
case ENCHANT:
return Collections.singletonList(new PParticle(location, 0.6, 0.6, 0.6, 1.0));
case ENCHANTED_HIT:
return Collections.singletonList(new PParticle(location, 0.4, 0.4, 0.4, 0.0));
case END_ROD:
return Collections.singletonList(new PParticle(location, 0.4, 0.4, 0.4, 0.0));
case ENTITY_EFFECT:
return Collections.singletonList(new PParticle(location, 0.4, 0.4, 0.4, 0.0));
case EXPLOSION:
return Collections.singletonList(new PParticle(location, 0.4, 0.4, 0.4, 0.0));
case EXPLOSION_EMITTER:
return Collections.singletonList(new PParticle(location, 0.4, 0.4, 0.4, 0.0));
case FALLING_DUST:
for (int i = 0; i < 2; i++)
particles.add(new PParticle(location.add(0, 0.75, 0), 0.6, 0.4, 0.6, 0.0));
return particles;
case FIREWORK:
return Collections.singletonList(new PParticle(location, 0.4, 0.4, 0.4, 0.0));
case FISHING:
return Collections.singletonList(new PParticle(location, 0.4, 0.4, 0.4, 0.0));
case FLAME:
return Collections.singletonList(new PParticle(location, 0.1, 0.1, 0.1, 0.05));
case FOOTSTEP:
return Collections.singletonList(new PParticle(location, 0.4, 0.4, 0.4, 0.0));
case HAPPY_VILLAGER:
return Collections.singletonList(new PParticle(location, 0.5, 0.5, 0.5, 0.0));
case HEART:
return Collections.singletonList(new PParticle(location, 0.6, 0.6, 0.6, 0.0));
case INSTANT_EFFECT:
return Collections.singletonList(new PParticle(location, 0.4, 0.4, 0.4, 0.0));
case ITEM:
return Collections.singletonList(new PParticle(location, 0.6, 0.6, 0.6, 0.0));
case ITEM_SLIME:
return Collections.singletonList(new PParticle(location, 0.4, 0.4, 0.4, 0.0));
case ITEM_SNOWBALL:
return Collections.singletonList(new PParticle(location, 0.4, 0.4, 0.4, 0.0));
case LARGE_SMOKE:
return Collections.singletonList(new PParticle(location, 0.4, 0.4, 0.4, 0.0));
case LAVA:
return Collections.singletonList(new PParticle(location, 0.4, 0.4, 0.4, 0.0));
case MYCELIUM:
return Collections.singletonList(new PParticle(location, 0.4, 0.4, 0.4, 0.0));
case NAUTILUS:
return Collections.singletonList(new PParticle(location, 0.5, 0.5, 0.5, 1.0));
case NOTE:
return Collections.singletonList(new PParticle(location, 0.6, 0.6, 0.6, 0.0));
case POOF:
return Collections.singletonList(new PParticle(location, 0.4, 0.4, 0.4, 0.0));
case PORTAL:
return Collections.singletonList(new PParticle(location, 0.5, 0.5, 0.5, 1.0));
case RAIN:
return Collections.singletonList(new PParticle(location, 0.4, 0.4, 0.4, 0.0));
case SMOKE:
return Collections.singletonList(new PParticle(location, 0.4, 0.4, 0.4, 0.0));
case SPELL:
return Collections.singletonList(new PParticle(location, 0.4, 0.4, 0.4, 0.0));
case SPIT:
return Collections.singletonList(new PParticle(location, 0.6, 0.6, 0.6, 0.0));
case SPLASH:
return Collections.singletonList(new PParticle(location, 0.4, 0.4, 0.4, 0.0));
case SQUID_INK:
return Collections.singletonList(new PParticle(location, 0.6, 0.6, 0.6, 0.0));
case SWEEP_ATTACK:
return Collections.singletonList(new PParticle(location, 0.4, 0.4, 0.4, 0.0));
case TOTEM_OF_UNDYING:
return Collections.singletonList(new PParticle(location, 0.6, 0.6, 0.6, 0.0));
case UNDERWATER:
for (int i = 0; i < 5; i++)
particles.add(new PParticle(location, 0.5, 0.5, 0.5, 0.0));
return particles;
case WITCH:
return Collections.singletonList(new PParticle(location, 0.4, 0.4, 0.4, 0.0));
default:
return Collections.singletonList(new PParticle(location, 0.4, 0.4, 0.4, 0.0));
}
}
public void updateTimers() {
}
public String getName() {
return "normal";
}
public boolean canBeFixed() {
return true;
}
}

View file

@ -1,29 +1,46 @@
package com.esophose.playerparticles.styles;
import java.util.ArrayList;
import java.util.List;
import org.bukkit.Location;
import com.esophose.playerparticles.PPlayer;
import com.esophose.playerparticles.particles.ParticlePair;
import com.esophose.playerparticles.styles.api.PParticle;
import com.esophose.playerparticles.styles.api.ParticleStyle;
public class ParticleStyleOrbit implements ParticleStyle {
private float step = 0;
private static double[] cos, sin;
private static final int orbs = 3;
private static final int numSteps = 120;
private int step = 0;
static {
cos = new double[120];
sin = new double[120];
int i = 0;
for (double n = 0; n < numSteps; n++) {
cos[i] = -Math.cos(n / numSteps * Math.PI * 2);
sin[i] = -Math.sin(n / numSteps * Math.PI * 2);
i++;
}
}
public PParticle[] getParticles(PPlayer pplayer, Location location) {
int orbs = 3;
PParticle[] particles = new PParticle[orbs];
public List<PParticle> getParticles(ParticlePair particle, Location location) {
List<PParticle> particles = new ArrayList<PParticle>();
for (int i = 0; i < orbs; i++) {
double dx = -(Math.cos((step / 120) * (Math.PI * 2) + (((Math.PI * 2) / orbs) * i)));
double dz = -(Math.sin((step / 120) * (Math.PI * 2) + (((Math.PI * 2) / orbs) * i)));
particles[i] = new PParticle(new Location(location.getWorld(), location.getX() + dx, location.getY(), location.getZ() + dz));
double dx = cos[(step + (numSteps / orbs * i)) % numSteps];
double dz = sin[(step + (numSteps / orbs * i)) % numSteps];
particles.add(new PParticle(location.clone().add(dx, 0, dz)));
}
return particles;
}
public void updateTimers() {
step++;
if (step > 120) {
if (step > numSteps) {
step = 0;
}
}

View file

@ -0,0 +1,33 @@
package com.esophose.playerparticles.styles;
import java.util.ArrayList;
import java.util.List;
import org.bukkit.Location;
import com.esophose.playerparticles.particles.ParticlePair;
import com.esophose.playerparticles.styles.api.PParticle;
import com.esophose.playerparticles.styles.api.ParticleStyle;
public class ParticleStyleOverhead implements ParticleStyle {
public List<PParticle> getParticles(ParticlePair particle, Location location) {
List<PParticle> particles = new ArrayList<PParticle>();
particles.add(new PParticle(location.clone().add(0, 1.75, 0), 0.4F, 0.1F, 0.4F, 0.0F));
particles.add(new PParticle(location.clone().add(0, 1.75, 0), 0.4F, 0.1F, 0.4F, 0.0F));
return particles;
}
public void updateTimers() {
}
public String getName() {
return "overhead";
}
public boolean canBeFixed() {
return true;
}
}

View file

@ -1,15 +1,18 @@
package com.esophose.playerparticles.styles;
import java.util.Collections;
import java.util.List;
import org.bukkit.Location;
import com.esophose.playerparticles.PPlayer;
import com.esophose.playerparticles.particles.ParticlePair;
import com.esophose.playerparticles.styles.api.PParticle;
import com.esophose.playerparticles.styles.api.ParticleStyle;
public class ParticleStylePoint implements ParticleStyle {
public PParticle[] getParticles(PPlayer pplayer, Location location) {
return new PParticle[] { new PParticle(location.add(0.0, 1.5, 0.0)) };
public List<PParticle> getParticles(ParticlePair particle, Location location) {
return Collections.singletonList(new PParticle(location.clone().add(0.0, 1.5, 0.0)));
}
public void updateTimers() {

View file

@ -1,39 +1,59 @@
package com.esophose.playerparticles.styles;
import java.util.ArrayList;
import java.util.List;
import org.bukkit.Location;
import com.esophose.playerparticles.PPlayer;
import com.esophose.playerparticles.particles.ParticlePair;
import com.esophose.playerparticles.styles.api.PParticle;
import com.esophose.playerparticles.styles.api.ParticleStyle;
public class ParticleStyleQuadhelix implements ParticleStyle {
private float stepX = 0;
private float stepY = 0;
private static double[] cos, sin;
private static final int orbs = 4;
private static int maxStepX = 80;
private static int maxStepY = 60;
private int stepX = 0;
private int stepY = 0;
private boolean reverse = false;
static {
cos = new double[maxStepX];
sin = new double[maxStepX];
int i = 0;
for (double n = 0; n < maxStepX; n++) {
cos[i] = -Math.cos(n / maxStepX * Math.PI * 2);
sin[i] = -Math.sin(n / maxStepX * Math.PI * 2);
i++;
}
}
public PParticle[] getParticles(PPlayer pplayer, Location location) {
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 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));
public List<PParticle> getParticles(ParticlePair particle, Location location) {
List<PParticle> particles = new ArrayList<PParticle>();
for (int i = 0; i < orbs; i++) {
int step = (stepX + (maxStepX / orbs) * i) % maxStepX;
double dx = cos[step] * ((60 - Math.abs(stepY)) / (double)maxStepY);
double dy = (stepY / (double)maxStepY) * 1.5;
double dz = sin[step] * ((60 - Math.abs(stepY)) / (double)maxStepY);
particles.add(new PParticle(location.clone().add(dx, dy, dz)));
}
return particles;
}
public void updateTimers() {
stepX++;
if (stepX > 90) {
if (stepX > maxStepX) {
stepX = 0;
}
if (reverse) {
stepY++;
if (stepY > 60) reverse = false;
if (stepY > maxStepY) reverse = false;
} else {
stepY--;
if (stepY < -60) reverse = true;
if (stepY < -maxStepY) reverse = true;
}
}

View file

@ -0,0 +1,62 @@
package com.esophose.playerparticles.styles;
import java.util.ArrayList;
import java.util.List;
import org.bukkit.Location;
import com.esophose.playerparticles.particles.ParticlePair;
import com.esophose.playerparticles.styles.api.PParticle;
import com.esophose.playerparticles.styles.api.ParticleStyle;
public class ParticleStyleRings implements ParticleStyle {
private static double[] cos, sin;
private int index = 0;
static {
cos = new double[32];
sin = new double[32];
int i = 0;
for (double n = 0; n < Math.PI * 2; n += Math.PI / 16) {
cos[i] = Math.sin(n);
sin[i] = Math.cos(n);
i++;
}
}
public List<PParticle> getParticles(ParticlePair particle, Location location) {
List<PParticle> particles = new ArrayList<PParticle>();
particles.add(new PParticle(location.clone().add(cos[index], sin[index], sin[index])));
particles.add(new PParticle(location.clone().add(cos[wrap(index + 16)], sin[wrap(index + 16)], sin[wrap(index + 16)])));
particles.add(new PParticle(location.clone().add(cos[wrap(index + 16)], sin[index], sin[wrap(index + 16)])));
particles.add(new PParticle(location.clone().add(cos[index], sin[wrap(index + 16)], sin[index])));
return particles;
}
/**
* Wraps an index around the cos/sin array length
*
* @param index The index to wrap
* @return The wrapped index
*/
private int wrap(int index) {
return index % cos.length;
}
public void updateTimers() {
index = (index + 1) % cos.length;
}
public String getName() {
return "rings";
}
public boolean canBeFixed() {
return true;
}
}

View file

@ -1,28 +1,30 @@
package com.esophose.playerparticles.styles;
import java.util.ArrayList;
import java.util.List;
import org.bukkit.Location;
import com.esophose.playerparticles.PPlayer;
import com.esophose.playerparticles.particles.ParticlePair;
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];
public List<PParticle> getParticles(ParticlePair particle, Location location) {
int density = 15;
double radius = 1.5f;
List<PParticle> particles = new ArrayList<PParticle>();
for (int i = 0; i < particleCount; i++) {
for (int i = 0; i < density; 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));
double dx = radius * Math.sin(phi) * Math.cos(theta);
double dy = radius * Math.sin(phi) * Math.sin(theta);
double dz = radius * Math.cos(phi);
particles.add(new PParticle(location.clone().add(dx, dy, dz)));
}
return particles;

View file

@ -1,39 +1,50 @@
package com.esophose.playerparticles.styles;
import java.util.Collections;
import java.util.List;
import org.bukkit.Location;
import com.esophose.playerparticles.PPlayer;
import com.esophose.playerparticles.particles.ParticlePair;
import com.esophose.playerparticles.styles.api.PParticle;
import com.esophose.playerparticles.styles.api.ParticleStyle;
public class ParticleStyleSpin implements ParticleStyle {
private float step = 0;
private static double[] cos, sin;
private static final int maxSteps = 30;
private int step = 0;
static {
cos = new double[maxSteps];
sin = new double[maxSteps];
int i = 0;
for (double n = 0; n < Math.PI * 2; n += Math.PI * 2 / maxSteps) {
cos[i] = Math.cos(n);
sin[i] = Math.sin(n);
i++;
}
}
public PParticle[] getParticles(PPlayer pplayer, Location location) {
int points = 15;
double radius = .5;
double slice = 2 * Math.PI / points;
double angle = slice * (step % 15);
double newX = location.getX() + radius * Math.cos(angle);
double newY = location.getY() + 1.5;
double newZ = location.getZ() + radius * Math.sin(angle);
return new PParticle[] { new PParticle(new Location(location.getWorld(), newX, newY, newZ)) };
}
public List<PParticle> getParticles(ParticlePair particle, Location location) {
double radius = .5;
double newX = location.getX() + radius * cos[step];
double newY = location.getY() + 1.5;
double newZ = location.getZ() + radius * sin[step];
return Collections.singletonList(new PParticle(new Location(location.getWorld(), newX, newY, newZ)));
}
public void updateTimers() {
step++;
if (step > 30) {
step = 0;
}
}
public void updateTimers() {
step = (step + 1) % maxSteps;
}
public String getName() {
return "spin";
}
public boolean canBeFixed() {
return true;
public String getName() {
return "spin";
}
public boolean canBeFixed() {
return true;
}
}

View file

@ -5,23 +5,23 @@ import java.util.List;
import org.bukkit.Location;
import com.esophose.playerparticles.PPlayer;
import com.esophose.playerparticles.particles.ParticlePair;
import com.esophose.playerparticles.styles.api.PParticle;
import com.esophose.playerparticles.styles.api.ParticleStyle;
public class ParticleStyleSpiral implements ParticleStyle {
private float stepX = 0;
private int stepX = 0;
public PParticle[] getParticles(PPlayer pplayer, Location location) {
public List<PParticle> getParticles(ParticlePair particle, Location location) {
List<PParticle> particles = new ArrayList<PParticle>();
for (int stepY = -60; stepY < 60; stepY += 10) {
double dx = -(Math.cos(((stepX + stepY) / 90) * Math.PI * 2)) * 0.8;
double dx = -(Math.cos(((stepX + stepY) / 90D) * Math.PI * 2)) * 0.8;
double dy = stepY / 45D;
double dz = -(Math.sin(((stepX + stepY) / 90) * Math.PI * 2)) * 0.8;
particles.add(new PParticle(new Location(location.getWorld(), location.getX() + dx, location.getY() + dy, location.getZ() + dz)));
double dz = -(Math.sin(((stepX + stepY) / 90D) * Math.PI * 2)) * 0.8;
particles.add(new PParticle(location.clone().add(dx, dy, dz)));
}
return particles.toArray(new PParticle[particles.size()]);
return particles;
}
public void updateTimers() {

View file

@ -12,36 +12,36 @@ import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import com.esophose.playerparticles.PPlayer;
import com.esophose.playerparticles.manager.PPlayerDataManager;
import com.esophose.playerparticles.manager.DataManager;
import com.esophose.playerparticles.manager.ParticleManager;
import com.esophose.playerparticles.manager.PermissionManager;
import com.esophose.playerparticles.particles.PPlayer;
import com.esophose.playerparticles.particles.ParticlePair;
import com.esophose.playerparticles.styles.api.PParticle;
import com.esophose.playerparticles.styles.api.ParticleStyle;
public class ParticleStyleSwords implements ParticleStyle, Listener {
private static final List<String> SWORD_NAMES;
static {
SWORD_NAMES = new ArrayList<String>();
SWORD_NAMES.addAll(Arrays.asList("WOOD_SWORD", "STONE_SWORD", "IRON_SWORD", "GOLD_SWORD", "DIAMOND_SWORD"));
SWORD_NAMES.addAll(Arrays.asList("WOOD_SWORD", "STONE_SWORD", "IRON_SWORD", "GOLD_SWORD", "GOLDEN_SWORD", "DIAMOND_SWORD", "TRIDENT"));
}
public PParticle[] getParticles(PPlayer pplayer, Location location) {
PParticle[] baseParticles = DefaultStyles.THICK.getParticles(pplayer, location);
public List<PParticle> getParticles(ParticlePair particle, Location location) {
List<PParticle> baseParticles = DefaultStyles.THICK.getParticles(particle, location);
int multiplyingFactor = 3; // Uses the same logic as ParticleStyleThick except multiplies the resulting particles by 3x
PParticle[] particles = new PParticle[baseParticles.length * multiplyingFactor];
for (int i = 0; i < baseParticles.length * multiplyingFactor; i++) {
particles[i] = baseParticles[i % baseParticles.length];
List<PParticle> particles = new ArrayList<PParticle>();
for (int i = 0; i < baseParticles.size() * multiplyingFactor; i++) {
particles.add(baseParticles.get(i % baseParticles.size()));
}
return particles;
}
public void updateTimers() {
}
public String getName() {
@ -51,20 +51,20 @@ public class ParticleStyleSwords implements ParticleStyle, Listener {
public boolean canBeFixed() {
return false;
}
@EventHandler(priority = EventPriority.MONITOR)
public void onEntityDamageEntity(EntityDamageByEntityEvent event) {
if (event.getDamager() instanceof Player && event.getEntity() instanceof LivingEntity) {
Player player = (Player) event.getDamager();
LivingEntity entity = (LivingEntity) event.getEntity();
PPlayer pplayer = PPlayerDataManager.getInstance().getPPlayer(player.getUniqueId());
if (pplayer != null && pplayer.getParticleStyle() == DefaultStyles.SWORDS && PermissionManager.hasStylePermission(player, DefaultStyles.SWORDS)) {
if (player.getInventory().getItemInMainHand() != null && SWORD_NAMES.contains(player.getInventory().getItemInMainHand().getType().name())) {
PPlayer pplayer = DataManager.getPPlayer(player.getUniqueId());
if (pplayer != null) {
for (ParticlePair particle : pplayer.getActiveParticlesForStyle(DefaultStyles.SWORDS)) {
Location loc = entity.getLocation().clone().add(0, 1, 0);
ParticleManager.displayParticles(pplayer, DefaultStyles.SWORDS.getParticles(pplayer, loc));
ParticleManager.displayParticles(particle, DefaultStyles.SWORDS.getParticles(particle, loc));
}
}
}
}
}
}

View file

@ -1,20 +1,23 @@
package com.esophose.playerparticles.styles;
import java.util.ArrayList;
import java.util.List;
import org.bukkit.Location;
import com.esophose.playerparticles.PPlayer;
import com.esophose.playerparticles.particles.ParticlePair;
import com.esophose.playerparticles.styles.api.PParticle;
import com.esophose.playerparticles.styles.api.ParticleStyle;
public class ParticleStyleThick implements ParticleStyle {
public PParticle[] getParticles(PPlayer pplayer, Location location) {
PParticle[] baseParticles = DefaultStyles.NONE.getParticles(pplayer, location);
public List<PParticle> getParticles(ParticlePair particle, Location location) {
List<PParticle> baseParticles = DefaultStyles.NORMAL.getParticles(particle, 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];
int multiplyingFactor = 10; // Uses the same logic as ParticleStyleNormal except multiplies the resulting particles by 10x
List<PParticle> particles = new ArrayList<PParticle>();
for (int i = 0; i < baseParticles.size() * multiplyingFactor; i++) {
particles.add(baseParticles.get(i % baseParticles.size()));
}
return particles;
@ -27,7 +30,7 @@ public class ParticleStyleThick implements ParticleStyle {
public String getName() {
return "thick";
}
public boolean canBeFixed() {
return true;
}

View file

@ -0,0 +1,70 @@
/**
* The MIT License (MIT)
*
* Copyright (c) 2014 Slikey
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
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.particles.ParticlePair;
import com.esophose.playerparticles.styles.api.PParticle;
import com.esophose.playerparticles.styles.api.ParticleStyle;
public class ParticleStyleVortex implements ParticleStyle {
private double grow = .05f;
private double radials = Math.PI / 16;
private int helices = 4;
private int step = 0;
private int maxStep = 70;
public List<PParticle> getParticles(ParticlePair particle, Location location) {
List<PParticle> particles = new ArrayList<PParticle>();
double radius = 2 * (1 - (double)step / maxStep);
for (int i = 0; i < helices; i++) {
double angle = step * radials + (2 * Math.PI * i / helices);
Vector v = new Vector(Math.cos(angle) * radius, step * grow - 1, Math.sin(angle) * radius);
particles.add(new PParticle(location.clone().add(v)));
}
return particles;
}
public void updateTimers() {
step = (step + 1) % maxStep;
}
public String getName() {
return "vortex";
}
public boolean canBeFixed() {
return true;
}
}

View file

@ -6,7 +6,7 @@ import java.util.List;
import org.bukkit.Location;
import org.bukkit.util.Vector;
import com.esophose.playerparticles.PPlayer;
import com.esophose.playerparticles.particles.ParticlePair;
import com.esophose.playerparticles.styles.api.PParticle;
import com.esophose.playerparticles.styles.api.ParticleStyle;
import com.esophose.playerparticles.util.VectorUtils;
@ -15,18 +15,17 @@ public class ParticleStyleWings implements ParticleStyle {
private int spawnTimer = 0; // Spawn particles every 3 ticks
public PParticle[] getParticles(PPlayer pplayer, Location location) {
public List<PParticle> getParticles(ParticlePair particle, Location location) {
List<PParticle> particles = new ArrayList<PParticle>();
if (spawnTimer == 0) {
for (double t = 0; t < Math.PI * 2; t += Math.PI / 64) {
for (double t = 0; t < Math.PI * 2; t += Math.PI / 48) {
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));
particles.add(new PParticle(location.clone().add(v.getX(), v.getY(), v.getZ())));
}
}
return particles.toArray(new PParticle[particles.size()]);
return particles;
}
public void updateTimers() {

View file

@ -1,11 +1,3 @@
/**
* 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.styles.api;
import org.bukkit.Location;
@ -13,11 +5,12 @@ import org.bukkit.Location;
public class PParticle {
/**
* Data that affects the particle
* Data that determines where the particle will spawn
*/
private Location location;
private float speed;
private float xOff, yOff, zOff;
private double speed;
private double xOff, yOff, zOff;
private boolean directional;
/**
* The constructor with all the fancy parameters for customization
@ -27,13 +20,28 @@ public class PParticle {
* @param yOff The offset for the y-axis
* @param zOff The offset for the z-axis
* @param speed The speed the particle will move at
* @param directional If the particle should use the x, y, and z offsets as directions instead
*/
public PParticle(Location location, float xOff, float yOff, float zOff, float speed) {
public PParticle(Location location, double xOff, double yOff, double zOff, double speed, boolean directional) {
this.location = location;
this.xOff = xOff;
this.yOff = yOff;
this.zOff = zOff;
this.speed = speed;
this.directional = directional;
}
/**
* The constructor with all the fancy parameters for customization
*
* @param location The location to display the particle at
* @param xOff The offset for the x-axis
* @param yOff The offset for the y-axis
* @param zOff The offset for the z-axis
* @param speed The speed the particle will move at
*/
public PParticle(Location location, double xOff, double yOff, double zOff, double speed) {
this(location, xOff, yOff, zOff, speed, false);
}
/**
@ -43,7 +51,7 @@ public class PParticle {
* @param location The location to display the particles at
*/
public PParticle(Location location) {
this(location, 0.0F, 0.0F, 0.0F, 0.0F);
this(location, 0.0F, 0.0F, 0.0F, 0.0F, false);
}
/**
@ -75,16 +83,25 @@ public class PParticle {
*
* @return The particle's speed
*/
public float getSpeed() {
public double getSpeed() {
return this.speed;
}
/**
* Gets if the particle is directional
*
* @return If the particle is directional
*/
public boolean isDirectional() {
return this.directional;
}
/**
* Gets the offset on the x-axis for the particle
*
* @return The x-axis offset
*/
public float getXOff() {
public double getXOff() {
return this.xOff;
}
@ -93,7 +110,7 @@ public class PParticle {
*
* @return The y-axis offset
*/
public float getYOff() {
public double getYOff() {
return this.yOff;
}
@ -102,7 +119,7 @@ public class PParticle {
*
* @return The z-axis offset
*/
public float getZOff() {
public double getZOff() {
return this.zOff;
}

View file

@ -1,27 +1,21 @@
/**
* 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.styles.api;
import java.util.List;
import org.bukkit.Location;
import com.esophose.playerparticles.PPlayer;
import com.esophose.playerparticles.particles.ParticlePair;
public interface ParticleStyle {
/**
* Gets all the particles to display based on the style's logic
*
* @param pplayer The PPlayer to display the particles for
* @param particle The ParticlePair that contains the particle's data
* @param location The central location of the particles
* @return A list of all PParticles' to spawn
* @return A List of PParticles to spawn
*/
public PParticle[] getParticles(PPlayer pplayer, Location location);
public List<PParticle> getParticles(ParticlePair particle, Location location);
/**
* Used to update timers for animations, called once per particle tick
@ -41,5 +35,18 @@ public interface ParticleStyle {
* @return If the style can be used in a FixedParticleEffect
*/
public boolean canBeFixed();
/**
* Gets the ParticleStyle with the name given, returns null if not found
*
* @param styleName The string of the style to search for
* @return The ParticleStyle with the name requested
*/
public static ParticleStyle fromName(String styleName) {
for (ParticleStyle style : ParticleStyleManager.getStyles())
if (style.getName().equals(styleName)) return style;
return null;
}
}

View file

@ -1,14 +1,7 @@
/**
* 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.styles.api;
import java.util.ArrayList;
import java.util.List;
import com.esophose.playerparticles.PlayerParticles;
@ -17,8 +10,8 @@ public class ParticleStyleManager {
/**
* Arrays that contain all registered styles
*/
private static ArrayList<ParticleStyle> styles = new ArrayList<ParticleStyle>();
private static ArrayList<ParticleStyle> customHandledStyles = new ArrayList<ParticleStyle>();
private static List<ParticleStyle> styles = new ArrayList<ParticleStyle>();
private static List<ParticleStyle> customHandledStyles = new ArrayList<ParticleStyle>();
/**
* Registers a style that is put into the plugin's update loop
@ -26,13 +19,26 @@ public class ParticleStyleManager {
* @param style The style to add
*/
public static void registerStyle(ParticleStyle style) {
if (style == null) {
PlayerParticles.getPlugin().getLogger().severe("Tried to register a null style");
return;
}
if (style.getName() == null || style.getName().trim().equals("")) {
PlayerParticles.getPlugin().getLogger().severe("Tried to register a style with a null or empty name: '" + style.getName() + "'");
return;
}
for (ParticleStyle testAgainst : styles) {
if (testAgainst.getName().equalsIgnoreCase(style.getName())) {
PlayerParticles.getPlugin().getLogger().severe("Tried to register two styles with the same name spelling: " + style.getName());
PlayerParticles.getPlugin().getLogger().severe("Tried to register two styles with the same name spelling: '" + style.getName() + "'");
return;
} else if (testAgainst.equals(style)) {
PlayerParticles.getPlugin().getLogger().severe("Tried to register the same style twice: " + style.getName());
PlayerParticles.getPlugin().getLogger().severe("Tried to register the same style twice: '" + style.getName() + "'");
return;
}
}
styles.add(style);
}
@ -59,22 +65,20 @@ public class ParticleStyleManager {
/**
* Gets all registered styles
*
* @return An ArrayList of all registered styles
* @return A List of ParticleStyles that are registered
*/
public static ArrayList<ParticleStyle> getStyles() {
public static List<ParticleStyle> getStyles() {
return styles;
}
/**
* Gets the ParticleStyle with the name given, returns null if not found
* Removes all styles from the registry
*
* @param styleName The string of the style to search for
* @return The ParticleStyle with the name requested
* It is not recommended to call this
*/
public static ParticleStyle styleFromString(String styleName) {
for (ParticleStyle style : styles)
if (style.getName().equals(styleName)) return style;
return null;
public static void reset() {
styles.clear();
customHandledStyles.clear();
}
/**

View file

@ -1,11 +1,3 @@
/**
* 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.updater;
import org.bukkit.ChatColor;
@ -14,7 +6,7 @@ import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
import com.esophose.playerparticles.PlayerParticles;
import com.esophose.playerparticles.manager.MessageManager;
import com.esophose.playerparticles.manager.LangManager;
public class PluginUpdateListener implements Listener {
@ -27,9 +19,9 @@ public class PluginUpdateListener implements Listener {
public void onPlayerJoin(PlayerJoinEvent e) {
if (e.getPlayer().isOp()) {
if (PlayerParticles.updateVersion != null) { // @formatter:off
MessageManager.sendCustomMessage(e.getPlayer(), ChatColor.YELLOW + "An update (" + ChatColor.AQUA + "v" + PlayerParticles.updateVersion + ChatColor.YELLOW + ") is available! " +
"You are running " + ChatColor.AQUA + "v" + PlayerParticles.getPlugin().getDescription().getVersion() + ChatColor.YELLOW +
". https://dev.bukkit.org/projects/playerparticles");
LangManager.sendCustomMessage(e.getPlayer(), ChatColor.YELLOW + "An update (" + ChatColor.AQUA + "v" + PlayerParticles.updateVersion + ChatColor.YELLOW + ") is available! " +
"You are running " + ChatColor.AQUA + "v" + PlayerParticles.getPlugin().getDescription().getVersion() + ChatColor.YELLOW +
". https://dev.bukkit.org/projects/playerparticles");
} // @formatter:on
}
}

View file

@ -1,11 +1,3 @@
/**
* 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.util;
import java.util.ArrayList;
@ -14,6 +6,21 @@ import java.util.List;
import org.bukkit.Material;
public class ParticleUtils {
private static List<String> blockMaterials, itemMaterials;
static {
blockMaterials = new ArrayList<String>();
itemMaterials = new ArrayList<String>();
for (Material mat : Material.values()) {
if (mat.isBlock()) {
blockMaterials.add(mat.name().toLowerCase());
} else {
itemMaterials.add(mat.name().toLowerCase());
}
}
}
/**
* Finds a block/item as a material from a string
@ -34,7 +41,7 @@ public class ParticleUtils {
return material;
return null;
} // @formatter:on
/**
* Finds a block/item as a material from a list of possible strings
* Contains a fallback to the barrier icon just in case
@ -46,28 +53,28 @@ public class ParticleUtils {
Material mat = null;
for (String name : input) {
mat = closestMatch(name);
if (mat != null)
return mat;
if (mat != null) return mat;
}
if (mat == null)
mat = Material.BARRIER;
if (mat == null) mat = Material.BARRIER;
return mat;
}
/**
* Gets all block materials in the game
*
* @return A List of all block material names available in the game
*/
public static List<String> getAllBlockMaterials() {
List<String> materials = new ArrayList<String>();
for (Material mat : Material.values())
if (mat.isBlock())
materials.add(mat.name().toLowerCase());
return materials;
return blockMaterials;
}
/**
* Gets all item materials in the game
*
* @return A List of all item material names available in the game
*/
public static List<String> getAllItemMaterials() {
List<String> materials = new ArrayList<String>();
for (Material mat : Material.values())
if (!mat.isBlock())
materials.add(mat.name().toLowerCase());
return materials;
return itemMaterials;
}
/**
@ -86,7 +93,8 @@ public class ParticleUtils {
}
}
for (int i = 0; i < n.length; ++i)
if (n[i] != i + 1) return i + 1;
if (n[i] != i + 1)
return i + 1;
return n.length + 1;
}

View file

@ -32,7 +32,7 @@ public final class VectorUtils {
* Not instantiable
*/
private VectorUtils() {
}
/**

View file

@ -10,16 +10,32 @@
# Welcome to the beginning #
# ==================================================== #
# This value is the version of the plugin that last modified the config file
# Changing this value will reset your config on the next server reload / restart.
# I don't recommend changing it
# 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.2
version: 5.3
# Check for new versions of the plugin
# Default: true
check-updates: true
# The .lang file to use in the ./lang/ folder
# Default: 'default.lang'
lang-file: 'default.lang'
# If you're using other plugins to execute commands you may wish to turn off messages
# Default: true
messages-enabled: true
# Whether or not to use the message-prefix field when displaying messages
# Default: true
use-message-prefix: true
# The prefix to use for all PlayerParticles messages
# This is useless if use-message-prefix is set to false
# Default: '&7[&3PlayerParticles&7]'
message-prefix: '&7[&3PlayerParticles&7]'
# If the command /pp gui is enabled
# Disable this if you have your own custom GUI through another plugin
# Default: true
@ -32,6 +48,16 @@ disabled-worlds: []
# - your_world_name_here
# - add_more_under_these
# The maximum number of particles a player can apply at once
# The GUI will only display up to 21, don't set this any higher than that
# Default: 3
max-particles: 3
# The maximum number of groups a player can have saved
# The GUI will only display up to 21, don't set this any higher than that
# Default: 10
max-groups: 10
# Max fixed effects per player
# Default: 5
max-fixed-effects: 5
@ -40,8 +66,8 @@ max-fixed-effects: 5
# Determines how far away a player may create a fixed effect from themselves
# This measurement is in blocks
# Set to 0 for infinite distance
# Default: 128
max-fixed-effect-creation-distance: 128
# Default: 32
max-fixed-effect-creation-distance: 32
# How many ticks to wait before spawning more particles
# Increasing this value may cause less lag (if there was any), but will decrease prettiness
@ -50,387 +76,13 @@ max-fixed-effect-creation-distance: 128
# 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 cannot use the apostrophe character! ( ' ) #
# ================================================================ #
# From how many blocks away should a player be able to see the particles from another player?
# Default: 48
particle-render-range-player: 48
# If you're using other plugins to execute commands you may wish to turn off messages
# Default: true
messages-enabled: true
# Whether or not to use the message-prefix field when displaying messages
# Default: true
use-message-prefix: true
# The prefix to use for all PlayerParticle messages
# This is useless if use-message-prefix is set to false
# Default: '&7[&3PlayerParticles&7]'
message-prefix: '&7[&3PlayerParticles&7]'
# ------------- #
# Particles #
# ------------- #
# No Particle Permission
# Default: '&cYou do not have permission to use &b{TYPE} &cparticles!'
message-no-permission: '&cYou do not have permission to use &b{TYPE} &cparticles!'
# /pp list No Particles
# Default: '&cYou do not have permission to use any particles!'
message-no-particles: '&cYou do not have permission to use any particles!'
# Now Using Particles
# Default: '&aNow using &b{TYPE} &aparticles!'
message-now-using: '&aNow using &b{TYPE} &aparticles!'
# Cleared Particles
# Default: '&aYour particles have been cleared!'
message-cleared-particles: '&aYour particles have been cleared!'
# Invalid Particle Type
# Default: '&cInvalid particle type! &b/pp effects'
message-invalid-type: '&cInvalid particle type! &b/pp effects &c| &b/pp effect <type>'
# Particle Command Usage
# You should not change the text here, only the coloring
# Default: '&b/pp effect <type>'
message-particle-usage: '&b/pp effect <type>'
# -------------- #
# Styles #
# -------------- #
# No Style Permission
# Default: '&cYou do not have permission to use the style type &b{TYPE}&c!'
message-no-permission-style: '&cYou do not have permission to use the style type &b{TYPE}&c!'
# /pp styles No Styles
# Default: '&cYou do not have permission to use any styles!'
message-no-styles: '&cYou do not have permission to use any styles!'
# Now Using Style
# Default: '&aNow using the style type &b{TYPE}&a!'
message-now-using-style: '&aNow using the style type &b{TYPE}&a!'
# Cleared Style
# Default: '&aYour style has been cleared!'
message-cleared-style: '&aYour style has been cleared!'
# Invalid Style Type
# Default: '&cInvalid style type! &b/pp styles &c| &b/pp style <type>'
message-invalid-type-style: '&cInvalid style type! &b/pp styles &c| &b/pp style <type>'
# Style Command Usage
# You should not change the text here, only the coloring
# Default: '&b/pp style <type>'
message-style-usage: '&b/pp style <type>'
# ------------ #
# Data #
# ------------ #
# Data Usage
# Default: '&eYour current effect requires &b{TYPE} &edata!'
message-data-usage: '&eYour current effect requires &b{TYPE} &edata!'
# No Data Required
# Default: '&eYour current effect does not use any data!'
message-no-data-usage: '&eYour current effect does not use any data!'
# Data Applied
# Default: '&aYour &b{TYPE} &adata has been applied!'
message-data-applied: '&aYour &b{TYPE} &adata has been applied!'
# Invalid Data Arguments
# Default: '&cInvalid &b{TYPE} &cdata arguments!'
message-data-invalid-arguments: '&cInvalid &b{TYPE} &cdata arguments!'
# Unknown Material
# Default: '&cThe {TYPE} name you supplied is invalid!'
message-data-material-unknown: '&cThe &b{TYPE} &cname you supplied is invalid!'
# Mismatched Material
# Default: '&cThe material supplied is not of type &b{TYPE}&c!'
message-data-material-mismatch: '&cThe material supplied is not of type &b{TYPE}&c!'
# Note Data Usage
# You should not change the text here, only the coloring
# Default: '&b/pp data [<0-23>]|[rainbow]'
message-note-data-usage: '&b/pp data [<0-23>]|[rainbow]'
# Color Data Usage
# You should not change the text here, only the coloring
# Default: '&b/pp data [<0-255> <0-255> <0-255>]|[rainbow]'
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/ID>'
message-item-data-usage: '&b/pp data <itemName>'
# Block Data Usage
# You should not change the text here, only the coloring
# Default: '&b/pp data <blockName/ID>'
message-block-data-usage: '&b/pp data <blockName>'
# ---------------- #
# Prefixes #
# ---------------- #
# You Can Use Particles
# Default: '&eYou can use:'
message-use: '&eYou can use:&b'
# Usage
# Default: '&eUsage:'
message-usage: '&eUsage:'
# Available Commands
# Default: '&eAvailable commands: &beffect, effects, style, styles, data, fixed, reset, gui, worlds, version, help'
message-available-commands: '&eAvailable commands: &beffect, effects, style, styles, data, fixed, reset, gui, worlds, version, help'
# Disabled Worlds
# 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
# ----------------- #
# -- Create -- #
# Missing Creation Arguments
# Default: '&cUnable to create fixed effect, you are missing &b{TYPE} &crequired arguments!'
message-create-fixed-missing-args: '&cUnable to create fixed effect, you are missing &b{TYPE} &crequired arguments!'
# Invalid Coordinates
# Default: '&cUnable to create fixed effect, one or more coordinates you entered is invalid!'
message-create-fixed-invalid-coords: '&cUnable to create fixed effect, one or more coordinates you entered is invalid!'
# Coords Out Of Range
# Default: '&cUnable to create fixed effect, you must be within &b{TYPE}&c blocks of your desired location!'
message-create-fixed-out-of-range: '&cUnable to create fixed effect, you must be within &b{TYPE}&c blocks of your desired location!'
# Invalid Effect
# Default: '&cUnable to create fixed effect, an effect with the name &b{TYPE} &cdoes not exist!'
message-create-fixed-invalid-effect: '&cUnable to create fixed effect, an effect with the name &b{TYPE} &cdoes not exist!'
# No Permission Effect
# Default: '&cUnable to create fixed effect, you do not have permission to use the effect &b{TYPE}&c!'
message-create-fixed-no-permission-effect: '&cUnable to create fixed effect, you do not have permission to use the effect &b{TYPE}&c!'
# Invalid Style
# Default: '&cUnable to create fixed effect, a style with the name &b{TYPE} &cdoes not exist!'
message-create-fixed-invalid-style: '&cUnable to create fixed effect, a style with the name &b{TYPE} &cdoes not exist!'
# No Permission Style
# Default: '&cUnable to create fixed effect, you do not have permission to use the style &b{TYPE}&c!'
message-create-fixed-no-permission-style: '&cUnable to create fixed effect, you do not have permission to use the style &b{TYPE}&c!'
# Style Not Fixable
# Default: '&cThe style &b{TYPE} &cprovided can not be used in fixed effects!'
message-create-fixed-non-fixable-style: '&cThe style &b{TYPE} &ccan not be used in fixed effects!'
# Data Error
# Default: '&cUnable to create fixed effect, the data provided is not correct! This effect requires &b{TYPE}&c!'
message-create-fixed-data-error: '&cUnable to create fixed effect, the data provided is not correct! This effect requires &b{TYPE}&c data!'
# Creation Success
# Default: '&aYour fixed effect has been created!'
message-create-fixed-success: '&aYour fixed effect has been created!'
# -- Remove -- #
# Could Not Remove
# Default: '&cUnable to remove, you do not have a fixed effect with the id of &b{TYPE}&c!'
message-remove-fixed-nonexistant: '&cUnable to remove, you do not have a fixed effect with the id of &b{TYPE}&c!'
# No Args Remove
# Default: '&cYou did not specify an id to remove!'
message-remove-fixed-no-args: '&cYou did not specify an id to remove!'
# Invalid Args Remove
# Default: '&cUnable to remove, the id specified must be a number!'
message-remove-fixed-invalid-args: '&cUnable to remove, the id specified must be a number!'
# Effect Removed
# Default: '&aYour fixed effect with the id &b{TYPE}&a has been removed!'
message-remove-fixed-success: '&aYour fixed effect with the id &b{TYPE}&a has been removed!'
# -- List -- #
# List Success
# Default: '&eYou have fixed effects with these ids: &b'
message-list-fixed-success: '&eYou have fixed effects with these ids: &b'
# List None
# Default: '&eYou do not have any fixed effects!'
message-list-fixed-none: '&eYou do not have any fixed effects!'
# -- Info -- #
# Could Not Get Info
# Default: '&cUnable to get info, you do not have a fixed effect with the id of &b{TYPE}&c!'
message-info-fixed-nonexistant: '&cUnable to get info, you do not have a fixed effect with the id of &b{TYPE}&c!'
# No Args Info
# Default: '&cYou did not specify an id to display info for!'
message-info-fixed-no-args: '&cYou did not specify an id to display info for!'
# Invalid Args Info
# Default: '&cUnable to get info, the id specified must be a number!'
message-info-fixed-invalid-args: '&cUnable to get info, the id specified must be a number!'
# Fixed Effect Info
# Key:
# {0} = ID
# {1} = World Name
# {2} = World X Position
# {3} = World Y Position
# {4} = World Z Position
# {5} = Effect Name
# {6} = Style Name
# {7} = Data
# Default: '&eID: &b{0} &eWorld: &b{1} &eX: &b{2} &eY: &b{3} &eZ: &b{4} &eEffect: &b{5} &eStyle: &b{6} &eData: &b{7}'
message-info-fixed-info: '&eID: &b{0} &eWorld: &b{1} &eX: &b{2} &eY: &b{3} &eZ: &b{4} &eEffect: &b{5} &eStyle: &b{6} &eData: &b{7}'
# -- Clear -- #
# No Permission Clear
# Default: '&cYou do not have permission to clear fixed effects of other players!'
message-clear-no-permission: '&cYou do not have permission to clear fixed effects of other players!'
# No Arguments Clear
# Default: '&cYou did not provide a radius to clear fixed effects for!'
message-clear-no-args: '&cYou did not provide a radius to clear fixed effects for!'
# Invalid Arguments Clear
# Default: '&cThe radius you provided is invalid. Make sure it is a positive whole number!'
message-clear-invalid-args: '&cThe radius you provided is invalid. Make sure it is a positive whole number!'
# Successfully Cleared
# Key:
# {0} = Number of effects cleared
# {1} = The provided radius
# Default: '&aCleared &b{0} &afixed effects within &b{1} &ablocks of your location!'
message-clear-success: '&aCleared &b{0} &afixed effects within &b{1} &ablocks of your location!'
# -- Other -- #
# 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!'
# Reached Max Allowed
# Default: '&cYou have reached the maximum allowed fixed effects!'
message-max-fixed-effects-reached: '&cYou have reached the maximum allowed 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: '
# -- Command Descriptions -- #
# 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'
# Fixed Command Description For Clear
# 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. View other commands with &b/pp help&e or use &b/pp gui&e to avoid this message.'
message-gui-by-default: '&eWe opened the GUI for you because you did not specify a command. View other commands with &b/pp help&e or use &b/pp gui&e to avoid this message.'
# 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 #
# ------------- #
# Reset
# Default: '&aYour effect, style, and data have all been reset!'
message-reset: '&aYour effect, style, and data have all been reset!'
# Invalid Arguments
# Default: '&cInvalid arguments! &a/pp help'
message-invalid-arguments: '&cInvalid arguments! &b/pp help'
# Disabled Worlds None
# Default: '&eParticles are not disabled in any worlds!'
message-disabled-worlds-none: '&eParticles are not disabled in any worlds!'
# Command Usage
# Default: '&eCommand Usage: /pp <command>'
message-command-usage: '&eCommand Usage: &b/pp <command>'
# From how many blocks away should a player be able to see the particles from a fixed effect?
# Default: 192
particle-render-range-fixed-effect: 192
# ================================================================ #
# DATABASE CONFIGURATION #
@ -481,152 +133,215 @@ database-user-password: ''
# * 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 #
# * If two icons are listed, the second one is used for below MC 1.13 #
# =================================================================== #
gui-icon:
main-menu:
EFFECT: BLAZE_POWDER
STYLE: NETHER_STAR
DATA: BOOK
effect: # 1.13 and up
AMBIENT_ENTITY_EFFECT: BEACON
ANGRY_VILLAGER: IRON_DOOR
BARRIER: BARRIER
BLOCK: STONE
BUBBLE: BUBBLE_CORAL
BUBBLE_COLUMN_UP: MAGMA_BLOCK
BUBBLE_POP: BUBBLE_CORAL_FAN
CLOUD: WHITE_WOOL
CRIT: IRON_SWORD
CURRENT_DOWN: SOUL_SAND
DAMAGE_INDICATOR: BOW
DOLPHIN: DOLPHIN_SPAWN_EGG
DRAGON_BREATH: DRAGON_BREATH
DRIPPING_LAVA: LAVA_BUCKET
DRIPPING_WATER: WATER_BUCKET
DUST: REDSTONE
ENCHANT: ENCHANTING_TABLE
ENCHANTED_HIT: DIAMOND_SWORD
END_ROD: END_ROD
ENTITY_EFFECT: GLOWSTONE_DUST
EXPLOSION: FIRE_CHARGE
EXPLOSION_EMITTER: TNT
FALLING_DUST: SAND
FIREWORK: FIREWORK_ROCKET
FISHING: FISHING_ROD
FLAME: BLAZE_POWDER
HAPPY_VILLAGER: DARK_OAK_DOOR
HEART: POPPY
INSTANT_EFFECT: SPLASH_POTION
ITEM: ITEM_FRAME
ITEM_SLIME: SLIME_BALL
ITEM_SNOWBALL: SNOWBALL
LARGE_SMOKE: COBWEB
LAVA: MAGMA_CREAM
MYCELIUM: MYCELIUM
NAUTILUS: HEART_OF_THE_SEA
NONE: GLASS_PANE
NOTE: NOTE_BLOCK
POOF: FIREWORK_STAR
PORTAL: OBSIDIAN
RAIN: PUFFERFISH_BUCKET
SMOKE: TORCH
SPELL: POTION
SPIT: LLAMA_SPAWN_EGG
SPLASH: SALMON
SQUID_INK: INK_SAC
SWEEP_ATTACK: GOLDEN_SWORD
TOTEM_OF_UNDYING: TOTEM
UNDERWATER: TURTLE_HELMET
WITCH: CAULDRON
effect-legacy: # 1.9 to 1.12
AMBIENT_ENTITY_EFFECT: BEACON
ANGRY_VILLAGER: IRON_DOOR
BARRIER: BARRIER
BLOCK: STONE
BUBBLE: GLASS
CLOUD: WOOL
CRIT: IRON_SWORD
DAMAGE_INDICATOR: BOW
DRAGON_BREATH: DRAGONS_BREATH
DRIPPING_LAVA: LAVA_BUCKET
DRIPPING_WATER: WATER_BUCKET
DUST: REDSTONE
ENCHANT: ENCHANTMENT_TABLE
ENCHANTED_HIT: DIAMOND_SWORD
END_ROD: END_ROD
ENTITY_EFFECT: GLOWSTONE_DUST
EXPLOSION: FIREBALL
EXPLOSION_EMITTER: TNT
FALLING_DUST: SAND
FIREWORK: FIREWORK
FISHING: FISHING_ROD
FLAME: BLAZE_POWDER
FOOTSTEP: GRASS
HAPPY_VILLAGER: WOOD_DOOR
HEART: RED_ROSE
INSTANT_EFFECT: POTION
ITEM: ITEM_FRAME
ITEM_SLIME: SLIME_BALL
ITEM_SNOWBALL: SNOWBALL
LARGE_SMOKE: WEB
LAVA: MAGMA_CREAM
MYCELIUM: MYCEL
NONE: THIN_GLASS
NOTE: NOTE_BLOCK
POOF: FIREWORK_CHARGE
PORTAL: OBSIDIAN
RAIN: LAPIS_BLOCK
SMOKE: TORCH
SPELL: GLASS_BOTTLE
SPIT: PUMPKIN_SEEDS
SPLASH: FISH
SWEEP_ATTACK: GOLD_SWORD
TOTEM_OF_UNDYING: TOTEM
UNDERWATER: BOAT
WITCH: CAULDRON
style: # 1.13 and up
ARROWS: BOW
BEAM: POWERED_RAIL
BLOCKBREAK: IRON_PICKAXE
BLOCKEDIT: DISPENSER
BLOCKPLACE: OAK_PLANKS
CUBE: STONE
FEET: GRASS
HALO: ENDER_PORTAL_FRAME
HURT: CACTUS
MOVE: PISTON
NONE: GLASS_PANE
ORBIT: ENCHANTING_TABLE
POINT: STONE_BUTTON
QUADHELIX: NAUTILUS_SHELL
SPHERE: HEART_OF_THE_SEA
SPIN: BEACON
SPIRAL: HOPPER
SWORDS: IRON_SWORD
THICK: COBWEB
WINGS: ELYTRA
style-legacy: # 1.9 to 1.12
ARROWS: BOW
BEAM: POWERED_RAIL
BLOCKBREAK: IRON_PICKAXE
BLOCKEDIT: DISPENSER
BLOCKPLACE: WOOD
CUBE: STONE
FEET: GRASS
HALO: ENDER_PORTAL_FRAME
HURT: CACTUS
MOVE: PISTON_BASE
NONE: THIN_GLASS
ORBIT: ENCHANTMENT_TABLE
POINT: STONE_BUTTON
QUADHELIX: ACTIVATOR_RAIL
SPHERE: SNOW_BALL
SPIN: BEACON
SPIRAL: HOPPER
SWORDS: IRON_SWORD
THICK: VINE
WINGS: ELYTRA
gui-icon:
misc:
particles:
- BLAZE_POWDER
groups:
- CHEST
preset_groups:
- ENDER_CHEST
back:
- ARROW
create:
- WRITABLE_BOOK
- BOOK_AND_QUILL
edit_effect:
- FIREWORK_ROCKET
- FIREWORK
edit_style:
- NETHER_STAR
edit_data:
- BOOK
randomize:
- HOPPER
reset:
- BARRIER
effect:
ambient_entity_effect:
- BEACON
angry_villager:
- IRON_DOOR
barrier:
- BARRIER
block:
- STONE
bubble:
- BUBBLE_CORAL
- GLASS
bubble_column_up:
- MAGMA_BLOCK
bubble_pop:
- BUBBLE_CORAL_FAN
cloud:
- WHITE_WOOL
- WOOL
crit:
- IRON_SWORD
current_down:
- SOUL_SAND
damage_indicator:
- BOW
dolphin:
- DOLPHIN_SPAWN_EGG
dragon_breath:
- DRAGON_BREATH
- DRAGONS_BREATH
dripping_lava:
- LAVA_BUCKET
dripping_water:
- WATER_BUCKET
dust:
- REDSTONE
enchant:
- ENCHANTING_TABLE
- ENCHANTMENT_TABLE
enchanted_hit:
- DIAMOND_SWORD
end_rod:
- END_ROD
entity_effect:
- GLOWSTONE_DUST
explosion:
- FIRE_CHARGE
- FIREBALL
explosion_emitter:
- TNT
falling_dust:
- SAND
firework:
- FIREWORK_ROCKET
- FIREWORK
fishing:
- FISHING_ROD
flame:
- BLAZE_POWDER
footstep:
- GRASS
happy_villager:
- DARK_OAK_DOOR
- WOOD_DOOR
heart:
- POPPY
- RED_ROSE
instant_effect:
- SPLASH_POTION
- POTION
item:
- ITEM_FRAME
item_slime:
- SLIME_BALL
item_snowball:
- SNOWBALL
large_smoke:
- COBWEB
- WEB
lava:
- MAGMA_CREAM
mycelium:
- MYCELIUM
- MYCEL
nautilus:
- HEART_OF_THE_SEA
note:
- NOTE_BLOCK
poof:
- FIREWORK_STAR
- FIREWORK_CHARGE
portal:
- OBSIDIAN
rain:
- PUFFERFISH_BUCKET
- LAPIS_BLOCK
smoke:
- TORCH
spell:
- POTION
- GLASS_BOTTLE
spit:
- LLAMA_SPAWN_EGG
- PUMPKIN_SEEDS
splash:
- SALMON
- FISH
squid_ink:
- INK_SAC
sweep_attack:
- GOLDEN_SWORD
- GOLD_SWORD
totem_of_undying:
- TOTEM
underwater:
- TURTLE_HELMET
witch:
- CAULDRON
style:
arrows:
- BOW
batman:
- BAT_SPAWN_EGG
- COAL
beam:
- POWERED_RAIL
blockbreak:
- IRON_PICKAXE
blockedit:
- DISPENSER
blockplace:
- OAK_PLANKS
- WOOD
chains:
- TRIPWIRE_HOOK
companion:
- NAME_TAG
cube:
- STONE
feet:
- GRASS
halo:
- END_PORTAL_FRAME
- ENDER_PORTAL_FRAME
hurt:
- CACTUS
invocation:
- ENDER_EYE
- EYE_OF_ENDER
move:
- PISTON
- PISTON_BASE
normal:
- DIRT
orbit:
- ENCHANTING_TABLE
- ENCHANTMENT_TABLE
overhead:
- GLOWSTONE
point:
- STONE_BUTTON
quadhelix:
- NAUTILUS_SHELL
- ACTIVATOR_RAIL
rings:
- STRING
sphere:
- HEART_OF_THE_SEA
- SNOWBALL
spin:
- BEACON
spiral:
- HOPPER
swords:
- IRON_SWORD
thick:
- COBWEB
- WEB
vortex:
- GLOWSTONE_DUST
wings:
- ELYTRA
# That's everything! You reached the end of the configuration.
# Enjoy the plugin!
# Enjoy the plugin!

37
src/groups.yml Normal file
View file

@ -0,0 +1,37 @@
# ==================================================== #
# PRESET GROUPS #
# Information: #
# * The groups listed within this file will be #
# available to all players who have access to the #
# effect and style! #
# * The GUI is capable of displaying up to 28 groups. #
# * Feel free to create your own, they will be #
# available for users to select within the GUI! #
# * This file is not automatically updated. If you #
# want to reset the file to its defaults, simply #
# delete it and run the command '/pp reload'. #
# ==================================================== #
# Icons MUST use the names found at the link below:
# https://hub.spigotmc.org/javadocs/spigot/org/bukkit/Material.html
raincloud:
icon: 'ENDER_CHEST'
1:
effect: 'cloud'
style: 'overhead'
data: ''
2:
effect: 'rain'
style: 'overhead'
data: ''
rainbows:
icon: 'ENDER_CHEST'
1:
effect: 'dust'
style: 'orbit'
data: 'rainbow'
2:
effect: 'entity_effect'
style: 'feet'
data: 'rainbow'

253
src/lang/default.lang Normal file
View file

@ -0,0 +1,253 @@
# ================================================================ #
# default.lang (English) MESSAGE CONFIGURATION #
# Important Notes: #
# * You can use the & symbol to color the messages #
# * {#} Will be replaced with whatever that message requires #
# * Do NOT use the apostrophe character in any message! ( ' ) #
# * PLEASE MAKE YOUR OWN .lang FILE IF YOU WANT CUSTOM MESSAGES! #
# * This file will be overridden almost every plugin update! #
# ================================================================ #
# Command Errors
command-error-no-effects: '&cYou must have access to effects to use this command!'
command-error-unknown: '&cUnknown command, use &b/pp help &cfor a list of commands.'
# Command Descriptions
command-description-add: 'Add a particle to your active particles'
command-description-data: 'Check what type of data an effect uses'
command-description-default: 'The main command. By default, opens the GUI'
command-description-edit: 'Edit the effect, style, or data of an active particle'
command-description-effect: '&cThis command has been removed, use &b/pp help &cto find new commands'
command-description-effects: 'Display a list of effects you can use'
command-description-fixed: 'Create, edit, and remove fixed particle effects'
command-description-group: 'Save, load, and remove particle groups'
command-description-gui: 'Display the GUI for easy editing of particles'
command-description-help: 'Displays the help menu... You have arrived'
command-description-info: 'Gets the description of one of your active particles'
command-description-list: 'Lists the IDs of your active particles'
command-description-reload: 'Reloads the config.yml and lang file'
command-description-remove: 'Removes one of your active particles'
command-description-reset: 'Removes all your active particles'
command-description-style: '&cThis command has been removed, use &b/pp help &cto find new commands'
command-description-styles: 'Display a list of styles you can use'
command-description-version: 'Display the current version of the plugin and the author'
command-description-worlds: 'Find out what worlds particles are disabled in'
# Sub-Command Usage
command-description-fixed-create: '&e/pp fixed create <<x> <y> <z>|<looking>> <effect> <style> [data] - Creates a new fixed effect'
command-description-fixed-edit: '&e/pp fixed edit <id> <effect|style|data> <args> - Edit part of a fixed effect by its ID'
command-description-fixed-remove: '&e/pp fixed remove <ID> - Removes a fixed effect by its ID'
command-description-fixed-list: '&e/pp fixed list - Lists all IDs of your fixed effects'
command-description-fixed-info: '&e/pp fixed info <ID> - Gets info on one of your fixed effects'
command-description-fixed-clear: '&e/pp fixed clear <radius> - Clears all fixed effects of all players within the given radius'
command-description-group-save: '&e/pp group save <name> - Saves all active particles in a new group'
command-description-group-load: '&e/pp group load <name> - Loads all particles saved in a group'
command-description-group-remove: '&e/pp group remove <name> - Removes a group you have saved'
command-description-group-list: '&e/pp group list <name> - List all particle groups you have saved'
command-description-group-info: '&e/pp group info <name> - List the particles saved in the group'
# Command ID Lookup
id-invalid: '&cThe ID you entered is invalid, it must be a positive whole number!'
id-unknown: '&cYou do not have a particle applied with the ID &b{0}&c!'
# Add Command
add-reached-max: '&cUnable to apply particle, you have reached the maximum amount of &b{0} &callowed!'
add-particle-applied: '&aA new particle has been applied with the effect &b{0}&a, style &b{1}&a, and data &b{2}&a!'
# Data Command
data-no-args: '&cMissing argument for effect! Command usage: &b/pp data <effect>'
# Edit Command
edit-invalid-property: '&cAn invalid property &b{0} &cwas provided. Valid properties: &beffect&c, &bstyle&c, &bdata'
edit-success-effect: '&aYour particle with an ID of &b{0} &ahas had its effect changed to &b{1}&a!'
edit-success-style: '&aYour particle with an ID of &b{0} &ahas had its style changed to &b{1}&a!'
edit-success-data: '&aYour particle with an ID of &b{0} &ahas had its data changed to &b{1}&a!'
# Group Command
group-invalid: '&cA saved group or preset group does not exist with the name &b{0}&c!'
group-preset-no-permission: '&cYou are missing permission for an effect or style to use the preset group &b{0}&c!'
group-reserved: '&cThe group name &bactive &cis reserved and cannot be used!'
group-no-name: '&cYou did not provide a group name! &b/pp {0} <groupName>'
group-save-reached-max: '&cUnable to save group, you have reached the max number of groups!'
group-save-no-particles: '&cUnable to save group, you do not have any particles applied!'
group-save-success: '&aYour current particles have been saved under the group named &b{0}&a!'
group-save-success-overwrite: '&aThe group named &b{0} &ahas been updated with your current particles!'
group-load-success: '&aApplied &b{0} &aparticle(s) from your saved group named &b{1}&a!'
group-load-preset-success: '&aApplied &b{0} &aparticle(s) from the preset group named &b{1}&a!'
group-remove-preset: '&cYou cannot remove a preset group!'
group-remove-success: '&aRemoved the particle group named &b{0}&a!'
group-info-header: '&eThe group &b{0} &ehas the following particles:'
group-list-none: '&eYou do not have any particle groups saved!'
group-list-output: '&eYou have the following groups saved: &b{0}'
group-list-presets: '&eThe following preset groups are available: &b{0}'
# Reload Command
reload-success: '&aThe plugin has been reloaded!'
reload-no-permission: '&cYou do not have permission to reload the plugin settings!'
# Remove Command
remove-no-args: '&cYou did not specify an ID to remove! &b/pp remove <ID>'
remove-success: '&aYour particle with the ID &b{0} &ahas been removed!'
# List Command
list-none: '&eYou do not have any active particles!'
list-you-have: '&eYou have the following particles applied:'
list-output: '&eID: &b{0} &eEffect: &b{1} &eStyle: &b{2} &eData: &b{3}'
# Rainbow
rainbow: '&cr&6a&ei&an&bb&9o&dw'
# Random
random: 'random'
# Effects
effect-no-permission: '&cYou do not have permission to use the effect &b{0} &c!'
effect-invalid: '&cThe effect &b{0} &cdoes not exist! Use &b/pp effects &cfor a list of effects you can use.'
effect-list: '&eYou can use the following effects: &b{0}'
effect-list-empty: '&cYou do not have permission to use any effects!'
# Styles
style-no-permission: '&cYou do not have permission to use the style &b{0} &c!'
style-event-spawning-info: '&eNote: The style &b{0} &espawns particles based on an event.'
style-invalid: '&cThe style &b{0} &cdoes not exist! Use &b/pp styles &cfor a list of styles you can use.'
style-list: '&eYou can use the following styles: &b{0}'
# Data
data-usage-none: '&eThe effect &b{0} &edoes not use any data!'
data-usage-block: '&eThe effect &b{0} &erequires &bblock &edata! &bFormat: <blockName>'
data-usage-item: '&eThe effect &b{0} &erequires &bitem &edata! &bFormat: <itemName>'
data-usage-color: '&eThe effect &b{0} &erequires &bcolor &edata! &bFormat: <<0-255> <0-255> <0-255>>|<rainbow>|<random>'
data-usage-note: '&eThe effect &b{0} &erequires &bnote &edata! &bFormat: <0-24>|<rainbow>|<random>'
data-invalid-block: '&cThe &bblock &cdata you entered is invalid! &bFormat: <blockName>'
data-invalid-item: '&cThe &bitem &cdata you entered is invalid! &bFormat: <itemName>'
data-invalid-color: '&cThe &bcolor &cdata you entered is invalid! &bFormat: <<0-255> <0-255> <0-255>>|<rainbow>|<random>'
data-invalid-note: '&cThe &bnote &cdata you entered is invalid! &bFormat: <0-24>|<rainbow>|<random>'
data-invalid-material-not-item: '&cThe &bitem &cmaterial &b{0} &cyou entered is not an item!'
data-invalid-material-not-block: '&cThe &bblock &cmaterial &b{0} &cyou entered is not a block!'
data-invalid-material-item: '&cThe &bitem &cmaterial &b{0} you entered does not exist!'
data-invalid-material-block: '&cThe &bblock &cmaterial &b{0} you entered does not exist!'
# Worlds
disabled-worlds: '&eParticles are disabled in these worlds: &b{0}'
disabled-worlds-none: '&eParticles are not disabled in any worlds.'
# Reset
reset-success: '&aRemoved &b{0} &aactive particle(s)!'
# Fixed Effects
fixed-create-missing-args: '&cUnable to create fixed effect, you are missing &b{0} &crequired arguments!'
fixed-create-invalid-coords: '&cUnable to create fixed effect, one or more coordinates you entered is invalid!'
fixed-create-out-of-range: '&cUnable to create fixed effect, you must be within &b{0} &cblocks of your desired location!'
fixed-create-looking-too-far: '&cUnable to create fixed effect, you are standing too far away from the block you are looking at!'
fixed-create-effect-invalid: '&cUnable to create fixed effect, an effect with the name &b{0} &cdoes not exist!'
fixed-create-effect-no-permission: '&cUnable to create fixed effect, you do not have permission to use the effect &b{0}&c!'
fixed-create-style-invalid: '&cUnable to create fixed effect, a style with the name &b{0} &cdoes not exist!'
fixed-create-style-no-permission: '&cUnable to create fixed effect, you do not have permission to use the style &b{0}&c!'
fixed-create-style-non-fixable: '&cUnable to create fixed effect, the style &b{0} &ccan not be used in fixed effects!'
fixed-create-data-error: '&cUnable to create fixed effect, the data provided is not correct! Use &b/pp data <effect> &cto find the correct data format!'
fixed-create-success: '&aYour fixed effect has been created!'
fixed-edit-missing-args: '&cUnable to edit fixed effect, you are missing some arguments!'
fixed-edit-invalid-id: '&cUnable to edit fixed effect, the ID specified is invalid or does not exist!'
fixed-edit-invalid-property: '&cUnable to edit fixed effect, an invalid property was specified! Only &blocation&c, &beffect&c, &bstyle&c, and &bdata &care valid.'
fixed-edit-invalid-coords: '&cUnable to edit fixed effect, one or more coordinates you entered is invalid!'
fixed-edit-out-of-range: '&cUnable to edit fixed effect, you must be within &b{0} &cblocks of your desired location!'
fixed-edit-looking-too-far: '&cUnable to edit fixed effect, you are standing too far away from the block you are looking at!'
fixed-edit-effect-invalid: '&cUnable to edit fixed effect, an effect with the name &b{0} &cdoes not exist!'
fixed-edit-effect-no-permission: '&cUnable to edit fixed effect, you do not have permission to use the effect &b{0}&c!'
fixed-edit-style-invalid: '&cUnable to edit fixed effect, a style with the name &b{0} &cdoes not exist!'
fixed-edit-style-no-permission: '&cUnable to edit fixed effect, you do not have permission to use the style &b{0}&c!'
fixed-edit-style-non-fixable: '&cUnable to edit fixed effect, the style &b{0} &ccan not be used in fixed effects!'
fixed-edit-data-error: '&cUnable to edit fixed effect, the data provided is not correct! Use &b/pp data <effect> &cto find the correct data format!'
fixed-edit-data-none: '&cUnable to edit fixed effect, the effect does not require any data!'
fixed-edit-success: '&aUpdated the &b{0} &aof the fixed effect with an ID of &b{1}!'
fixed-remove-invalid: '&cUnable to remove fixed effect, you do not have a fixed effect with the ID of &b{0}&c!'
fixed-remove-no-args: '&cYou did not specify an ID to remove!'
fixed-remove-args-invalid: '&cUnable to remove, the ID specified must be a number!'
fixed-remove-success: '&aYour fixed effect with the ID &b{0} &ahas been removed!'
fixed-list-none: '&eYou do not have any fixed effects!'
fixed-list-success: '&eYou have fixed effects with these IDs: &b{0}'
fixed-info-invalid: '&cUnable to get info, you do not have a fixed effect with the ID of &b{0}&c!'
fixed-info-no-args: '&cYou did not specify an ID to display info for!'
fixed-info-invalid-args: '&cUnable to get info, the ID specified must be a number!'
fixed-info-success: '&eID: &b{0} &eWorld: &b{1} &eX: &b{2} &eY: &b{3} &eZ: &b{4} &eEffect: &b{5} &eStyle: &b{6} &eData: &b{7}'
fixed-clear-no-permission: '&cYou do not have permission to clear nearby fixed effects!'
fixed-clear-no-args: '&cYou did not provide a radius to clear fixed effects for!'
fixed-clear-invalid-args: '&cThe radius you provided is invalid, it must be a positive whole number!'
fixed-clear-success: '&aCleared &b{0} &afixed effects within &b{1} &ablocks of your location!'
fixed-no-permission: '&cYou do not have permission to use fixed effects!'
fixed-max-reached: '&cYou have reached the maximum allowed fixed effects!'
fixed-invalid-command: '&cInvalid sub-command for &b/pp fixed&c!'
# GUI
gui-disabled: '&cThe server administrator has disabled the GUI!'
gui-color-icon-name: '&a'
gui-color-info: '&e'
gui-color-subtext: '&b'
gui-color-unavailable: '&c'
gui-commands-info: 'Find info about commands with &b/pp help'
gui-back-button: 'Go Back'
gui-click-to-load: 'Click to load the following {0} particle(s):'
gui-shift-click-to-delete: 'Shift click to delete'
gui-particle-info: ' - ID: &b{0} &eEffect: &b{1} &eStyle: &b{2} &eData: &b{3}'
gui-playerparticles: 'PlayerParticles'
gui-active-particles: 'Active Particles: &b{0}'
gui-saved-groups: 'Saved Groups: &b{0}'
gui-fixed-effects: 'Fixed Effects: &b{0}'
gui-manage-your-particles: 'Manage Your Particles'
gui-manage-your-particles-description: 'Create, edit, and delete your particles'
gui-manage-your-groups: 'Manage Your Groups'
gui-manage-your-groups-description: 'Create, delete, and load your particle groups'
gui-load-a-preset-group: 'Load A Preset Group'
gui-load-a-preset-group-description: 'Load a premade particle group'
gui-save-group: 'Save New Group'
gui-save-group-description: 'You can save a new group using the following command:'
gui-save-group-description-2: '/pp group save <groupName>'
gui-reset-particles: 'Reset Your Particles'
gui-reset-particles-description: 'Deletes all your active particles'
gui-particle-name: 'Particle #{0}'
gui-click-to-edit-particle: 'Click to edit the effect, style, or data of this particle'
gui-editing-particle: 'Editing Particle #{0}'
gui-edit-effect: 'Edit Effect'
gui-edit-effect-description: 'Click to edit the effect of this particle'
gui-edit-style: 'Edit Style'
gui-edit-style-description: 'Click to edit the style of this particle'
gui-edit-data: 'Edit Data'
gui-edit-data-description: 'Click to edit the data of this particle'
gui-edit-data-unavailable: 'The effect of this particle does not use any data'
gui-data-none: 'none'
gui-create-particle: 'Create A New Particle'
gui-create-particle-description: 'Create a new particle with an effect, style, and data'
gui-create-particle-unavailable: 'You have reached the maximum amount of particles you can create'
gui-select-effect: 'Select Particle Effect'
gui-select-effect-description: 'Sets the particle effect to &b{0}'
gui-select-style: 'Select Particle Style'
gui-select-style-description: 'Sets the particle style to &b{0}'
gui-select-data: 'Select Particle Data'
gui-select-data-description: 'Sets the particle data to &b{0}'
gui-select-data-note: 'note #{0}'
gui-select-data-randomize-items: 'Randomize Items'
gui-select-data-randomize-items-description: 'Randomizes the items displayed'
gui-select-data-randomize-blocks: 'Randomize Blocks'
gui-select-data-randomize-blocks-description: 'Randomizes the blocks displayed'
gui-edit-data-color-red: '&cred'
gui-edit-data-color-orange: '&6orange'
gui-edit-data-color-yellow: '&eyellow'
gui-edit-data-color-lime-green: '&alime green'
gui-edit-data-color-green: '&2green'
gui-edit-data-color-blue: '&1blue'
gui-edit-data-color-cyan: '&3cyan'
gui-edit-data-color-light-blue: '&blight blue'
gui-edit-data-color-purple: '&5purple'
gui-edit-data-color-magenta: '&dmagenta'
gui-edit-data-color-pink: '&dpink'
gui-edit-data-color-brown: '&6brown'
gui-edit-data-color-black: '&8black'
gui-edit-data-color-gray: '&8gray'
gui-edit-data-color-light-gray: '&7light gray'
gui-edit-data-color-white: '&fwhite'

View file

@ -1,10 +1,10 @@
name: PlayerParticles
main: com.esophose.playerparticles.PlayerParticles
version: 5.2
version: 5.3
api-version: 1.13
description: Make particles around players in fancy ways.
description: Display particles around your player using customized styles and data!
author: Esophose
website: https://dev.bukkit.org/projects/playerparticles
commands:
pp:
description: The main PlayerParticles command. By default, opens the GUI.
description: The main PlayerParticles command. By default, opens the GUI.