Library [1.8] ParticleEffect v1.7

Discussion in 'Resources' started by DarkBladee12, Jun 20, 2013.

Thread Status:
Not open for further replies.
  1. Offline

    DarkBladee12

    ParticleEffect Library v1.7:


    Hey there guys, I wanna share my ParticleEffect library class which is based on microgeek's library with you. It has more features than microgeek's and is also update-proof due to the use of reflection! You can play any particle effect which is built into minecraft only for specific players or all in the world with this library. It also logs if it fails to create/send a packet. The code is now fully documented and can be used with ease. This library is also compatible with older versions of Bukkit! You can also submit pull requests on the official repository here! In order to be able use this library you can either copy the classes listed down below into your project or include it as a Maven dependency. The following list shows all the display methods of the latest version, besides javadocs can be found at this page! There's also a jenkins page for the latest releases here.

    Usage for all effects:
    • ParticleEffect.NAME.display(float offsetX, float offsetY, float offsetZ, float speed, int amount, Location center, double range);
    • ParticleEffect.NAME.display(float offsetX, float offsetY, float offsetZ, float speed, int amount, Location center, List<Player> players);
    • ParticleEffect.NAME.display(float offsetX, float offsetY, float offsetZ, float speed, int amount, Location center, Player... players);
    Usage for directional effects:
    • ParticleEffect.NAME.display(Vector direction, float speed, Location center, double range);
    • ParticleEffect.NAME.display(Vector direction, float speed, Location center, List<Player> players);
    • ParticleEffect.NAME.display(Vector direction, float speed, Location center, Player... players);
    Usage for colorable effects:
    • ParticleEffect.NAME.display(OrdinaryColor color, Location center, double range);
    • ParticleEffect.NAME.display(OrdinaryColor color, Location center, List<Player> players);
    • ParticleEffect.NAME.display(OrdinaryColor color, Location center, Player... players);
    • ParticleEffect.NAME.display(NoteColor color, Location center, double range);
    • ParticleEffect.NAME.display(NoteColor color, Location center, List<Player> players);
    • ParticleEffect.NAME.display(NoteColor color, Location center, Player... players
    Usage for effects which require data:
    • ParticleEffect.NAME.display(ItemData data, float offsetX, float offsetY, float offsetZ, float speed, int amount, Location center, double range);
    • ParticleEffect.NAME.display(ItemData data, float offsetX, float offsetY, float offsetZ, float speed, int amount, Location center, List<Player> players);
    • ParticleEffect.NAME.display(ItemData data, float offsetX, float offsetY, float offsetZ, float speed, int amount, Location center, Player... players);
    • ParticleEffect.NAME.display(ItemData data, Vector direction, float speed, Location center, double range);
    • ParticleEffect.NAME.display(ItemData data, Vector direction, float speed, Location center, List<Player> players);
    • ParticleEffect.NAME.display(ItemData data, Vector direction, float speed, Location center, Player... players);
    • ParticleEffect.NAME.display(BlockData data, float offsetX, float offsetY, float offsetZ, float speed, int amount, Location center, double range);
    • ParticleEffect.NAME.display(BlockData data, float offsetX, float offsetY, float offsetZ, float speed, int amount, Location center, List<Player> players);
    • ParticleEffect.NAME.display(BlockData data, float offsetX, float offsetY, float offsetZ, float speed, int amount, Location center, Player... players);
    • ParticleEffect.NAME.display(BlockData data, Vector direction, float speed, Location center, double range);
    • ParticleEffect.NAME.display(BlockData data, Vector direction, float speed, Location center, List<Player> players);
    • ParticleEffect.NAME.display(BlockData data, Vector direction, float speed, Location center, Player... players);
    Classes needed:
    • ParticleEffect class (Imports of ReflectionUtils are not included, you have to import that by yourself if you don't have this class in the same package as your ParticleEffect class!)
    • ReflectionUtils class (now compact and documentated)
    Maven Dependency Information:

    Code:
            <repository>
                <id>sinndev-repo</id>
                <url>http://repo.sinndev.com/content/groups/public/</url>
            </repository>
           
            <dependency>
                <groupId>com.darkblade12</groupId>
                <artifactId>particleeffect</artifactId>
                <version>1.7</version>
            </dependency>
           
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId>
                <version>2.4.1</version>
                <configuration>
                    <artifactSet>
                        <includes>
                            <include>com.darkblade12:*</include>
                        </includes>
                    </artifactSet>
                </configuration>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>

    Optional:

    • ParticleEffectData (Allows you to store attributes of a ParticleEffect and makes you able to serialize/deserialize them; Import of ParticleEffect is not included, you have to import that by yourself if you don't have these classes in the same package as your ParticleEffect class) Currently outdated!
    • ParticleDemo (A small plugin which allows you to display all kinds of particle effects ingame)

    Special Thanks:
     
    Last edited: Jul 22, 2015
  2. Offline

    Tzeentchful

    DarkBladee12
    Very nice. This will come handy in some of my mini game plugins.
     
  3. Offline

    ftbastler

  4. Offline

    DarkBladee12

    ftbastler The byte value in .playTileCrack(...) is the data value. It's useful for playing tilecracks with different wool blocks or sandstone since the data value changes how they look like ;)
     
  5. Offline

    ftbastler

    DarkBladee12 Thanks, good job on this lib - gonna use it a lot.
     
  6. Offline

    ICodeMaster

    What do the offsets do? Couldn't you offset it using just the location? Also is it possible to have the particles moving in a direction?
     
  7. Offline

    DSH105

    ICodeMaster
    Offset determines the general spread of the particles, and can play a part in the direction they travel. Without offset, it would just be a small blob of particles over the top of each other
     
  8. Offline

    ICodeMaster

    So if i wanted to make a swirling box of particle around a player i would have to use offsets to methoticly do it?
     
  9. Offline

    DarkBladee12

    ICodeMaster Yes you probably have to, but the offset is just the maximum value of the spread, they'll fly random every time even with the same offset.
     
  10. Offline

    ThunderWaffeMC

    Any screenshots/videos of the effects?
     
  11. Offline

    DarkBladee12

    ThunderWaffeMC There are no videos which show all these effects, you could try them out by simply implementing this class in your plugin and making a command which displays them^^
     
    ThunderWaffeMC likes this.
  12. Offline

    ICodeMaster

    Because i also mod with forge and i know for a fact that you can set parcticles with momentum. If i would set the offeset 1 at a time would you think it works? still fooling around with this library pretty awesome :D
     
  13. Offline

    KingMagnus

    I've made great use of your library in one of my plugins. This has been a great help.
     
  14. Offline

    djyee

    What's wrong with this code?

    djyee class::::::::
    Code:java
    1. package net._blackcraft;
    2.  
    3.  
    4.  
    5.  
    6. import org.bukkit.ChatColor;
    7. import org.bukkit.command.Command;
    8. import org.bukkit.command.CommandSender;
    9. import org.bukkit.entity.Player;
    10. import org.bukkit.plugin.Plugin;
    11. import org.bukkit.plugin.java.JavaPlugin;
    12.  
    13.  
    14.  
    15. public final class djyee extends JavaPlugin {
    16.  
    17.  
    18.  
    19. public void onEnable(){
    20. getLogger().info("Attachment active");
    21.  
    22. }
    23.  
    24. public void onDisable(){
    25. getLogger().info("Attachment passive");
    26. }
    27.  
    28. public boolean onCommand(CommandSender sender, Command cmd, String label, String args[]){
    29.  
    30. if(cmd.getName().equalsIgnoreCase("bar")){
    31. Player player1 = sender.getServer().getPlayer(args[0]);
    32. PacketUtils.displayTextBar(player1, ChatColor.GREEN + "Hello there, " + player1.getName() + "!");
    33. ParticleEffect.ANGRY_VILLAGER.play(null, 0, 0, 0, 0, 0, 0);
    34.  
    35.  
    36. }
    37. return false;
    38.  
    39. }
    40.  
    41. public static Plugin getInstance() {
    42. // TODO Auto-generated method stub
    43. return null;
    44. }
    45.  
    46. }


    ParticleEffect class:::
    Code:java
    1. package net._blackcraft;
    2.  
    3.  
    4. import java.lang.reflect.Constructor;
    5. import java.lang.reflect.Field;
    6. import java.lang.reflect.Method;
    7. import java.util.HashMap;
    8. import java.util.Map;
    9. import java.util.Map.Entry;
    10.  
    11. import org.bukkit.Bukkit;
    12. import org.bukkit.Location;
    13. import org.bukkit.entity.Player;
    14.  
    15. /**
    16. * ParticleEffect Library v1.0
    17. *
    18. * This particle effect library was created by DarkBlade12 based off content from microgeek
    19. * You are free to use it, modify it and redistribute it under the condition to give credit to me and microgeek
    20. *
    21. * @author DarkBlade12
    22. */
    23. public enum ParticleEffect {
    24.  
    25. HUGE_EXPLOSION("hugeexplosion", 0), LARGE_EXPLODE("largeexplode", 1), FIREWORKS_SPARK("fireworksSpark", 2), BUBBLE("bubble", 3), SUSPEND("suspend", 4), DEPTH_SUSPEND("depthSuspend", 5), TOWN_AURA(
    26. "townaura", 6), CRIT("crit", 7), MAGIC_CRIT("magicCrit", 8), MOB_SPELL("mobSpell", 9), MOB_SPELL_AMBIENT("mobSpellAmbient", 10), SPELL("spell", 11), INSTANT_SPELL("instantSpell", 12), WITCH_MAGIC(
    27. "witchMagic", 13), NOTE("note", 14), PORTAL("portal", 15), ENCHANTMENT_TABLE("enchantmenttable", 16), EXPLODE("explode", 17), FLAME("flame", 18), LAVA("lava", 19), FOOTSTEP("footstep", 20), SPLASH(
    28. "splash", 21), LARGE_SMOKE("largesmoke", 22), CLOUD("cloud", 23), RED_DUST("reddust", 24), SNOWBALL_POOF("snowballpoof", 25), DRIP_WATER("dripWater", 26), DRIP_LAVA("dripLava", 27), SNOW_SHOVEL(
    29. "snowshovel", 28), SLIME("slime", 29), HEART("heart", 30), ANGRY_VILLAGER("angryVillager", 31), HAPPY_VILLAGER("happyVillager", 32);
    30.  
    31. private String name;
    32. private int id;
    33.  
    34. ParticleEffect(String name, int id) {
    35. this.name = name;
    36. this.id = id;
    37. }
    38.  
    39. public String getName() {
    40. return name;
    41. }
    42.  
    43. public int getId() {
    44. return id;
    45. }
    46.  
    47. private static final Map<String, ParticleEffect> NAME_MAP = new HashMap<String, ParticleEffect>();
    48. private static final Map<Integer, ParticleEffect> ID_MAP = new HashMap<Integer, ParticleEffect>();
    49. static {
    50. for (ParticleEffect effect : values()) {
    51. NAME_MAP.put(effect.name, effect);
    52. ID_MAP.put(effect.id, effect);
    53. }
    54. }
    55.  
    56. public static ParticleEffect fromName(String name) {
    57. if (name == null) {
    58. return null;
    59. }
    60. for (Entry<String, ParticleEffect> e : NAME_MAP.entrySet()) {
    61. if (e.getKey().equalsIgnoreCase(name)) {
    62. return e.getValue();
    63. }
    64. }
    65. return null;
    66. }
    67.  
    68. public static ParticleEffect fromId(int id) {
    69. return ID_MAP.get(id);
    70. }
    71.  
    72. /**
    73. * Plays a particle effect at a location which is only shown to a specific player.
    74. */
    75. public void play(Player p, Location loc, float offsetX, float offsetY, float offsetZ, float speed, int amount) {
    76. sendPacket(p, createNormalPacket(this, loc, offsetX, offsetY, offsetZ, speed, amount));
    77. }
    78.  
    79. /**
    80. * Plays a particle effect at a location which is shown to all players in the current world.
    81. */
    82. public void play(Location loc, float offsetX, float offsetY, float offsetZ, float speed, int amount) {
    83. Object packet = createNormalPacket(this, loc, offsetX, offsetY, offsetZ, speed, amount);
    84. for (Player p : loc.getWorld().getPlayers()) {
    85. sendPacket(p, packet);
    86. }
    87. }
    88.  
    89. /**
    90. * Plays a particle effect at a location which is shown to all players whitin a certain range in the current world.
    91. */
    92. public void play(Location loc, double range, float offsetX, float offsetY, float offsetZ, float speed, int amount) {
    93. Object packet = createNormalPacket(this, loc, offsetX, offsetY, offsetZ, speed, amount);
    94. for (Player p : loc.getWorld().getPlayers()) {
    95. if (p.getLocation().distance(loc) <= range) {
    96. sendPacket(p, packet);
    97. }
    98. }
    99. }
    100.  
    101. /**
    102. * Plays a tilecrack effect at a location which is only shown to a specific player.
    103. */
    104. public static void playTileCrack(Player p, Location loc, int id, byte data, float offsetX, float offsetY, float offsetZ, int amount) {
    105. sendPacket(p, createTileCrackPacket(id, data, loc, offsetX, offsetY, offsetZ, amount));
    106. }
    107.  
    108. /**
    109. * Plays a tilecrack effect at a location which is shown to all players in the current world.
    110. */
    111. public static void playTileCrack(Location loc, int id, byte data, float offsetX, float offsetY, float offsetZ, int amount) {
    112. Object packet = createTileCrackPacket(id, data, loc, offsetX, offsetY, offsetZ, amount);
    113. for (Player p : loc.getWorld().getPlayers()) {
    114. sendPacket(p, packet);
    115. }
    116. }
    117.  
    118. /**
    119. * Plays a tilecrack effect at a location which is shown to all players within a certain range in the current world.
    120. */
    121. public static void playTileCrack(Location loc, double range, int id, byte data, float offsetX, float offsetY, float offsetZ, int amount) {
    122. Object packet = createTileCrackPacket(id, data, loc, offsetX, offsetY, offsetZ, amount);
    123. for (Player p : loc.getWorld().getPlayers()) {
    124. if (p.getLocation().distance(loc) <= range) {
    125. sendPacket(p, packet);
    126. }
    127. }
    128. }
    129.  
    130. /**
    131. * Plays an iconcrack effect at a location which is only shown to a specific player.
    132. */
    133. public static void playIconCrack(Player p, Location loc, int id, float offsetX, float offsetY, float offsetZ, int amount) {
    134. sendPacket(p, createIconCrackPacket(id, loc, offsetX, offsetY, offsetZ, amount));
    135. }
    136.  
    137. /**
    138. * Plays an iconcrack effect at a location which is shown to all players in the current world.
    139. */
    140. public static void playIconCrack(Location loc, int id, float offsetX, float offsetY, float offsetZ, int amount) {
    141. Object packet = createIconCrackPacket(id, loc, offsetX, offsetY, offsetZ, amount);
    142. for (Player p : loc.getWorld().getPlayers()) {
    143. sendPacket(p, packet);
    144. }
    145. }
    146.  
    147. /**
    148. * Plays an iconcrack effect at a location which is shown to all players within a certain range in the current world.
    149. */
    150. public static void playIconCrack(Location loc, double range, int id, float offsetX, float offsetY, float offsetZ, int amount) {
    151. Object packet = createIconCrackPacket(id, loc, offsetX, offsetY, offsetZ, amount);
    152. for (Player p : loc.getWorld().getPlayers()) {
    153. if (p.getLocation().distance(loc) <= range) {
    154. sendPacket(p, packet);
    155. }
    156. }
    157. }
    158.  
    159. private Object createNormalPacket(ParticleEffect effect, Location loc, float offsetX, float offsetY, float offsetZ, float speed, int amount) {
    160. return createPacket(effect.getName(), loc, offsetX, offsetY, offsetZ, speed, amount);
    161. }
    162.  
    163. private static Object createTileCrackPacket(int id, byte data, Location loc, float offsetX, float offsetY, float offsetZ, int amount) {
    164. return createPacket("tilecrack_" + id + "_" + data, loc, offsetX, offsetY, offsetZ, 0.1F, amount);
    165. }
    166.  
    167. private static Object createIconCrackPacket(int id, Location loc, float offsetX, float offsetY, float offsetZ, int amount) {
    168. return createPacket("iconcrack_" + id, loc, offsetX, offsetY, offsetZ, 0.1F, amount);
    169. }
    170.  
    171. private static Object createPacket(String effectName, Location loc, float offsetX, float offsetY, float offsetZ, float speed, int amount) {
    172. try {
    173. if (amount <= 0) {
    174. throw new IllegalArgumentException("Amount of particles has to be greater than 0!");
    175. }
    176. Object packet = ReflectionUtil.getClass("Packet63WorldParticles");
    177. ReflectionUtil.setValue(packet, "a", effectName);
    178. ReflectionUtil.setValue(packet, "b", (float) loc.getX());
    179. ReflectionUtil.setValue(packet, "c", (float) loc.getY());
    180. ReflectionUtil.setValue(packet, "d", (float) loc.getZ());
    181. ReflectionUtil.setValue(packet, "e", offsetX);
    182. ReflectionUtil.setValue(packet, "f", offsetY);
    183. ReflectionUtil.setValue(packet, "g", offsetZ);
    184. ReflectionUtil.setValue(packet, "h", speed);
    185. ReflectionUtil.setValue(packet, "i", amount);
    186. return packet;
    187. } catch (Exception e) {
    188. Bukkit.getLogger().warning("[ParticleEffect] Failed to create a particle packet!");
    189. return null;
    190. }
    191. }
    192.  
    193. private static void sendPacket(Player p, Object packet) {
    194. if (packet == null) {
    195. return;
    196. }
    197. try {
    198. Object entityPlayer = ReflectionUtil.getMethod("getHandle", p.getClass(), 0).invoke(p);
    199. Object playerConnection = entityPlayer.getClass().getField("playerConnection").get(entityPlayer);
    200. ReflectionUtil.getMethod("sendPacket", playerConnection.getClass(), 1).invoke(playerConnection, packet);
    201. } catch (Exception e) {
    202. Bukkit.getLogger().warning("[ParticleEffect] Failed to send a particle packet to " + p.getName() + "!");
    203. }
    204. }
    205.  
    206. private static class ReflectionUtil {
    207. public static Object getClass(String name, Object... args) throws Exception {
    208. Class<?> c = Class.forName(ReflectionUtil.getPackageName() + "." + name);
    209. int params = 0;
    210. if (args != null) {
    211. params = args.length;
    212. }
    213. for (Constructor<?> co : c.getConstructors()) {
    214. if (co.getParameterTypes().length == params) {
    215. return co.newInstance(args);
    216. }
    217. }
    218. return null;
    219. }
    220.  
    221. public static Method getMethod(String name, Class<?> c, int params) {
    222. for (Method m : c.getMethods()) {
    223. if (m.getName().equals(name) && m.getParameterTypes().length == params) {
    224. return m;
    225. }
    226. }
    227. return null;
    228. }
    229.  
    230. public static void setValue(Object instance, String fieldName, Object value) throws Exception {
    231. Field field = instance.getClass().getDeclaredField(fieldName);
    232. field.setAccessible(true);
    233. field.set(instance, value);
    234. }
    235.  
    236. public static String getPackageName() {
    237. return "net.minecraft.server." + Bukkit.getServer().getClass().getPackage().getName().replace(".", ",").split(",")[3];
    238. }
    239. }
    240. }
     
  15. Offline

    DarkBladee12

    djyee Umm your location is "null" in this line, that's why it won't work: "
    ParticleEffect.ANGRY_VILLAGER.play(null, 0, 0, 0, 0, 0, 0);"
     
  16. Offline

    Zarkopafilis

    DarkBladee12
    Speed doesnt do anything :p
    Also , can someone explain what do the offsets do?Thanks a lot! Awesome
     
  17. Offline

    Ultimate_n00b

    Offset.. like how off it is from the original point.
     
  18. Offline

    Zarkopafilis

  19. Offline

    DarkBladee12

    Zarkopafilis Speed does do something, but not on all particle effects. For some it changes the displaying speed and for others it dermines the colors. It's kinda weird value^^
     
  20. Offline

    Zarkopafilis

    Ah , Notch...

    DarkBladee12 Mind explaining tilecrack/iconcrack?

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: Oct 29, 2015
  21. Offline

    stirante

    Zarkopafilis Iconcrack are particles from item texture when this item is broken (you mine something with pickaxe and it loses it's durability). Tilecrack are particles made when you are mining block.
     
  22. Offline

    Zarkopafilis

    stirante Ok. I use your more projectiles in combination with this one and some other stuff that I coded and it is freaking awesome. Just unbelievable. I will PM you the video I am going to make previewing the server!
     
  23. Offline

    stirante

    Zarkopafilis But my MoreProjectiles already uses this lib :p
     
  24. Offline

    Zarkopafilis

    Dafuq? xD ... fixing project...
     
  25. Offline

    WavyWonderz

    I want to simulate a tool breaking (the particle that is emitted when the tool breaks), I would want to use playIconCrack, right?

    If so, can you tell me what's wrong with this code
    Code:java
    1. ParticleEffect.playIconCrack(player.getLocation(), player.getItemInHand().getTypeId(), 0, 0, 0, 100);

    *Edit*

    Managed to basically do it with this code (not much changed, other than the amount and the y offset)
    Code:java
    1. ParticleEffect.playIconCrack(player.getLocation(), player.getItemInHand().getTypeId(), 0, 1, 0, 1);

    but it still doesn't look exactly the same, if anyone could help me, yah.
    When it breaks normally (vanilla) the particles seem to be in front of the player, these seem to go everywhere...
     
  26. Offline

    Wingzzz

    Then you must create the particles in front of the player via the location, or using the offset values.
     
  27. Offline

    DarkBladee12

    WavyWonderz The offset values determine where particles will go, so you have to figure out what offset values minecraft uses when displaying this effect!
     
  28. Offline

    WavyWonderz


    Annndd... how might I do that?


    Depending on which way they're facing, the offsets will change... Is there any minecraft Wiki page I can look at for how minecraft offsets the particles?
     
  29. Offline

    MTN


    Some performance suggestions:
    1)
    Particles only have a certain range where they can be seen at the client, so sending these Packets to every player on the world is a lot of wasted performance. Here you can see the clientside particle range: Minecraft Wiki. In my version I just took a max range of ~20. I would suggest overloading the methods, for example:

    Code:java
    1.  
    2. public static final double DEFAULT_RANGE = 20;
    3. public void play(Location loc, float offsetX, float offsetY, float offsetZ, float speed, int amount) {
    4. play(loc, DEFAULT_RANGE , offsetX, offsetY, offsetZ, speed, amount);
    5. }
    6. }

    same thing for the other methods.
    2.)
    Changing this:
    Code:java
    1.  
    2. for (Player p : loc.getWorld().getPlayers()) {
    3. if (p.getLocation().distance(loc) <= range) {
    4. sendPacket(p, packet);
    5. }
    6. }

    to this:
    Code:java
    1.  
    2. double rangedSquared = ranged*ranged;
    3. for (Player p : loc.getWorld().getPlayers()) {
    4. if (p.getLocation().distanceSquared(loc) <= rangedSquared) {
    5. sendPacket(p, packet);
    6. }
    7. }
    8.  

    This is a small thing, but most CPUs love to add and multiply, but are bad (or not so fast) at division and calculating the square root of something are multiple divisions. If you might remember from math, calculation of a distance goes like this:

    sqrt((x2-x1)^2+(y1-y2)^2+(z1-z2)^2);
    Bukkit has the distanceSquared method on purpose ;)

    3.)
    This is more of a wild guess, since I don't know a lot about reflection performance, but you could probably cache the packet constructor and make it a singleton.

    Just play around with it. Send some packets and just try it out. There is wiki page about particles, but nothing about offsets. Again, try it out.

    Normally the offset describes how much the particles will spread in a certain direction, setting every offset to around 5.0 will for example result in particles spawning at random positions inside the cube with the width of 5. Set the amount to something big if you play around, just to see what I mean.

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: Oct 29, 2015
    glen3b, Jamboozlez and sgavster like this.
  30. Offline

    DarkBladee12

    MTN These are some good suggestions which will be implemented soon! I'm already about to recode this library to make it more efficient. (I also made my ReflectionUtil better) Caching the constructor would work and save performance, since it doesn't need to search for the constructor every time a new packet is created!
     
Thread Status:
Not open for further replies.

Share This Page