[Util] FireworkEffectPlayer v1.0

Discussion in 'Resources' started by codename_B, Dec 30, 2012.

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

    codename_B

    Pastebin: http://pastebin.com/Wi5974m4

    I figured out a way to create the firework effect, and used reflection to avoid directly tapping into net.minecraft.server.
    Feel free to use this in your plugins (also it appears that there's a limit of ~30 to the number of firework explosions that will display at one point in time on the client).

    I welcome feedback, and I'd love to see any plugins you make using it!

    Code:
    package com.bpermissions;
    
    import java.lang.reflect.Method;
    
    import org.bukkit.FireworkEffect;
    import org.bukkit.entity.Firework;
    import org.bukkit.inventory.meta.FireworkMeta;
    import org.bukkit.Location;
    import org.bukkit.World;
    
    /**
     * FireworkEffectPlayer v1.0
     * 
     * FireworkEffectPlayer provides a thread-safe and (reasonably) version independant way to instantly explode a FireworkEffect at a given location.
     * You are welcome to use, redistribute, modify and destroy your own copies of this source with the following conditions:
     * 
     * 1. No warranty is given or implied.
     * 2. All damage is your own responsibility.
     * 3. You provide credit publicly to the original source should you release the plugin.
     * 
     * @author codename_B
     */
    public class FireworkEffectPlayer {
        
        /*
         * Example use:
         * 
         * public class FireWorkPlugin implements Listener {
         * 
         * FireworkEffectPlayer fplayer = new FireworkEffectPlayer();
         * 
         * @EventHandler
         * public void onPlayerLogin(PlayerLoginEvent event) {
         *   fplayer.playFirework(event.getPlayer().getWorld(), event.getPlayer.getLocation(), Util.getRandomFireworkEffect());
         * }
         * 
         * }
         */
        
        // internal references, performance improvements
        private Method world_getHandle = null;
        private Method nms_world_broadcastEntityEffect = null;
        private Method firework_getHandle = null;
        
        /**
         * Play a pretty firework at the location with the FireworkEffect when called
         * @param world
         * @param loc
         * @param fe
         * @throws Exception
         */
        public void playFirework(World world, Location loc, FireworkEffect fe) throws Exception {
            // Bukkity load (CraftFirework)
            Firework fw = (Firework) world.spawn(loc, Firework.class);
            // the net.minecraft.server.World
            Object nms_world = null;
            Object nms_firework = null;
            /*
             * The reflection part, this gives us access to funky ways of messing around with things
             */
            if(world_getHandle == null) {
                // get the methods of the craftbukkit objects
                world_getHandle = getMethod(world.getClass(), "getHandle");
                firework_getHandle = getMethod(fw.getClass(), "getHandle");
            }
            // invoke with no arguments
            nms_world = world_getHandle.invoke(world, (Object[]) null);
            nms_firework = firework_getHandle.invoke(fw, (Object[]) null);
            // null checks are fast, so having this seperate is ok
            if(nms_world_broadcastEntityEffect == null) {
                // get the method of the nms_world
                nms_world_broadcastEntityEffect = getMethod(nms_world.getClass(), "broadcastEntityEffect");
            }
            /*
             * Now we mess with the metadata, allowing nice clean spawning of a pretty firework (look, pretty lights!)
             */
            // metadata load
            FireworkMeta data = (FireworkMeta) fw.getFireworkMeta();
            // clear existing
            data.clearEffects();
            // power of one
            data.setPower(1);
            // add the effect
            data.addEffect(fe);
            // set the meta
            fw.setFireworkMeta(data);
            /*
             * Finally, we broadcast the entity effect then kill our fireworks object
             */
            // invoke with arguments
            nms_world_broadcastEntityEffect.invoke(nms_world, new Object[] {nms_firework, (byte) 17});
            // remove from the game
            fw.remove();
        }
        
        /**
         * Internal method, used as shorthand to grab our method in a nice friendly manner
         * @param cl
         * @param method
         * @return Method (or null)
         */
        private static Method getMethod(Class<?> cl, String method) {
            for(Method m : cl.getMethods()) {
                if(m.getName().equals(method)) {
                    return m;
                }
            }
            return null;
        }
    
    }
    
     
  2. Offline

    LaxWasHere

  3. Offline

    MrMag518

    Wow I got some good luck here, was just going to start an adventure of searching after methods to do this.. then I found this. Thanks!
     
  4. Offline

    chasechocolate

    Cool! I hope to use this in one of my future plugins!
     
  5. Offline

    GeekyCompz

    Hello there, I have tried both importing both Utils but neither of them work. I am in the listener file.
     
  6. Offline

    codename_B

    The "Util" is an imaginary class that *you* have to make, to provide you with the random firework.
     
  7. Offline

    GeekyCompz

    Who do I put inside this class file?
     
  8. Offline

    codename_B

    Code:
    public static void getRandomEffect() {
    return FireworkEffect.builder().withType(Type.BALL).withColor(Color.RED).build();
    }
    
     
  9. Offline

    Rprrr

    codename_B
    Just wanted to post what I made with your fireworkeffectplayer. :p
     
  10. Offline

    LaxWasHere

    <3's Lightning storm.
     
  11. Offline

    codename_B

    You're welcome ;)
     
  12. Offline

    Ne0nx3r0

    I tried this out, for some reason I'm getting:
    Code:
    java.lang.IllegalArgumentException: Cannot spawn an entity for org.bukkit.entity.Firework
            at org.bukkit.craftbukkit.v1_4_6.CraftWorld.spawn(CraftWorld.java:1001)
            at org.bukkit.craftbukkit.v1_4_6.CraftWorld.spawn(CraftWorld.java:781)
            at org.bukkit.craftbukkit.v1_4_6.CraftWorld.spawnEntity(CraftWorld.java:328)
            at com.gmail.ne0nx3r0.utils.FireworkVisualEffect.playFirework(FireworkVisualEffect.java:54)
    
    Line 54 being:
    Calling it with:
    Code:
                    fireworks.playFirework(
                        livingEntity.getWorld(), livingEntity.getLocation(),
                        FireworkEffect
                            .builder()
                            .with(Type.BURST)
                            .withColor(Color.WHITE)
                            .build()
                    );
    Any ideas on what I'm doing wrong?
     
  13. Offline

    codename_B

    Maybe not on a bukkit that can spawn fireworks? Try latest beta.
     
  14. Offline

    evilmidget38

    codename_B Nice job on the documentation and commenting. I really appreciate the effort you put towards documentation(bPerms, for example), as far too many plugins/examples lack this documentation. It makes reading your code rather pleasant.

    Ne0nx3r0 I just looked at the CraftWorld code for where it throws the exception, and the lines don't line up with your stacktrace. You're almost definitely running an old build.
     
  15. Offline

    codename_B

    I try to comment so that if I immediately lost all my memory, I'd be able to figure out what I was doing :)
     
    chasechocolate likes this.
  16. Offline

    Ne0nx3r0

    Turns out it was an outdated version; I thought I was using a version that was compatible with your code, but I guess not.

    Thanks!
     
  17. Offline

    Kainzo

    So is there a method to explode the firework at the target instead of shooting it into the air? I'm trying to make a skill that does direct damage and just has the ball-explosion of the firework show up directly at the player....
     
  18. Offline

    codename_B

    That's what that is.
     
  19. Offline

    Kainzo

    Perhaps I'm confused, andrew2060 and I were trying to do it and it still shooting it into the air.
    Wanna see the src? maybe we did something wrong.
     
  20. Offline

    codename_B

    Please. Look at Rprrr 's video to see what this should be able to do.
     
  21. Offline

    Kainzo

    heh, wow that's impressive.
     
    phondeux likes this.
  22. Offline

    codename_B

    I'd be happy and interested to see why yours isn't working like that btw.
     
  23. Offline

    chasechocolate

    How did you make the small bursts form a circle?
     
  24. Offline

    Rprrr

    chasechocolate
    I used a method that formed a hollow circle around the player, added all those locations to a list and then looped through them using a repeating task.
     
  25. Offline

    chasechocolate

    What was the method?
     
  26. Offline

    Rprrr

    chasechocolate
    I used this method:
    Code:
        public static List<Location> circle (Player player, Location loc, Integer r, Integer h, Boolean hollow, Boolean sphere, int plus_y) {
            List<Location> circleblocks = new ArrayList<Location>();
            int cx = loc.getBlockX();
            int cy = loc.getBlockY();
            int cz = loc.getBlockZ();
            for (int x = cx - r; x <= cx +r; x++)
                for (int z = cz - r; z <= cz +r; z++)
                    for (int y = (sphere ? cy - r : cy); y < (sphere ? cy + r : cy + h); y++) {
                        double dist = (cx - x) * (cx - x) + (cz - z) * (cz - z) + (sphere ? (cy - y) * (cy - y) : 0);
                        if (dist < r*r && !(hollow && dist < (r-1)*(r-1))) {
                            Location l = new Location(loc.getWorld(), x, y + plus_y, z);
                            circleblocks.add(l);
                            }
                        }
         
            return circleblocks;
        }
    With a radius of 10, a height of 1, hollow to true, sphere to false and plus_y to 10.
     
  27. Offline

    Kainzo

    codename_B So I've integrated this into a lot of my skills on Herocraft. My issue now is its creating the firework at the users feet and not their head... effects like Creeper / STAR are being cut off.

    Any thoughts?
     
  28. Offline

    chasechocolate

    Kainzo
    player.getLocation().getBlockY() - 1? Just edit the 1 until you find it to work how you want it to.
     
  29. Offline

    Kainzo

    Yah, I figured it out by adding the location.
     
  30. Hey,

    works great, but how do I spawn fireworks without sound?
     
    xBlazeTECH likes this.
Thread Status:
Not open for further replies.

Share This Page