Particle packet library

Discussion in 'Resources' started by microgeek, Mar 31, 2013.

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

    microgeek

    I saw another thread for this, but imho, it was no the best, here's better formatted class.

    Code:
    package me.microgeek.plugins.template.utilities;
     
    import net.minecraft.server.v1_5_R1.Packet63WorldParticles;
     
    import org.bukkit.Location;
    import org.bukkit.craftbukkit.v1_5_R1.entity.CraftPlayer;
    import org.bukkit.entity.Player;
     
    public enum ParticleEffects {
     
        HUGE_EXPLOSION("hugeexplosion"),
        LARGE_EXPLODE("largeexplode"),
        FIREWORKS_SPARK("fireworksSpark"),
        BUBBLE("bubble"),
        SUSPEND("suspend"),
        DEPTH_SUSPEND("depthSuspend"),
        TOWN_AURA("townaura"),
        CRIT("crit"),
        MAGIC_CRIT("magicCrit"),
        MOB_SPELL("mobSpell"),
        MOB_SPELL_AMBIENT("mobSpellAmbient"),
        SPELL("spell"),
        INSTANT_SPELL("instantSpell"),
        WITCH_MAGIC("witchMagic"),
        NOTE("note"),
        PORTAL("portal"),
        ENCHANTMENT_TABLE("enchantmenttable"),
        EXPLODE("explode"),
        FLAME("flame"),
        LAVA("lava"),
        FOOTSTEP("footstep"),
        SPLASH("splash"),
        LARGE_SMOKE("largesmoke"),
        CLOUD("cloud"),
        RED_DUST("reddust"),
        SNOWBALL_POOF("snowballpoof"),
        DRIP_WATER("dripWater"),
        DRIP_LAVA("dripLava"),
        SNOW_SHOVEL("snowshovel"),
        SLIME("slime"),
        HEART("heart"),
        ANGRY_VILLAGER("angryVillager"),
        HAPPY_VILLAGER("happerVillager"),
        ICONCRACK("iconcrack_"),
        TILECRACK("tilecrack_");
       
        private String particleName;
       
        ParticleEffects(String particleName) {
            this.particleName = particleName;
        }
     
        public void sendToPlayer(Player player, Location location, float offsetX, float offsetY, float offsetZ, float speed, int count) throws Exception {
            Packet63WorldParticles packet = new Packet63WorldParticles();
            ReflectionUtilities.setValue(packet, "a", particleName);
            ReflectionUtilities.setValue(packet, "b", (float) location.getX());
            ReflectionUtilities.setValue(packet, "c", (float) location.getY());
            ReflectionUtilities.setValue(packet, "d", (float) location.getZ());
            ReflectionUtilities.setValue(packet, "e", offsetX);
            ReflectionUtilities.setValue(packet, "f", offsetY);
            ReflectionUtilities.setValue(packet, "g", offsetZ);
            ReflectionUtilities.setValue(packet, "h", speed);
            ReflectionUtilities.setValue(packet, "i", count);
            ((CraftPlayer) player).getHandle().playerConnection.sendPacket(packet);
        }
       
    }
    Code:
    package me.microgeek.plugins.template.utilities;
     
    import java.lang.reflect.Field;
     
    public class ReflectionUtilities {
     
        /**
        * sets a value of an {@link Object} via reflection
        *
        * @param instance instance the class to use
        * @param fieldName the name of the {@link Field} to modify
        * @param value the value to set
        * @throws Exception
        */
        public static void setValue(Object instance, String fieldName, Object value) throws Exception {
            Field field = instance.getClass().getDeclaredField(fieldName);
            field.setAccessible(true);
            field.set(instance, value);
        }
     
        /**
        * get a value of an {@link Object}'s {@link Field}
        *
        * @param instance the target {@link Object}
        * @param fieldName name of the {@link Field}
        * @return the value of {@link Object} instance's {@link Field} with the
        *        name of fieldName
        * @throws Exception
        */
        public static Object getValue(Object instance, String fieldName) throws Exception {
            Field field = instance.getClass().getDeclaredField(fieldName);
            field.setAccessible(true);
            return field.get(instance);
        }
     
    }

    Enjoy chumps, and happy coding.
     
  2. Offline

    chasechocolate

    Thanks :D there's going to be tons of crazy crap you can do with these :p

    microgeek found a typo (I think): your HAPPY_VILLAGER should be "happyVillager".

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: May 31, 2016
    GrandmaJam and ShearsSheep like this.
  3. Offline

    MCForger

    chasechocolate
    Love that effect
    microgeek
    Mine wasn't supposed to be a library just a simple look you can do it like this kind of thing
     
  4. Offline

    microgeek

    My bad, I wrote those Strings at 6am, thanks for the heads up!
     
    mine-care likes this.
  5. Offline

    stirante

    What with tilecrack and itemcrack? Maybe add static method like sendToPlayerItemcrack and sendToPlayerTileCrack. Another thing is I confirmed for now only for 2 particles that speed is actually color. And I think you could name your enum more user-friendly. Like instead of RED_DUST something like REDSTONE_PARTICLES. Also what if someone wants to show particles to all players? He will do for loop which will execute your method. This way plugin like that would create a lot of the same packets. I already created API for that but it would be third API here so I won't publish it. But nice idea for method sendToPlayer in enum. I'm definetly stealing this idea :p

    EDIT:Since when there is 'Grum' instead of 'Tahg' next to reply and like button? :D
     
  6. Offline

    microgeek

    Since I released it, I've added two more methods, sendParticleToPlayers(List<Player>) and sendParticleToLocation(Location), I'll update it later today.
     
  7. Offline

    DarkBladee12

    microgeek Thanks for the great work, I'm definitely going to use this ;)
     
  8. Offline

    microgeek

    No problem. =)
     
  9. Offline

    CreeperShift

    Dang, this is cool :3

    If only this would not restrict users to use MC 1.5 :( and I would use it right now :'(
     
  10. Offline

    DSH105

    stirante
    With those colours (the speed value on some effects), what values have you used? I've been able to get the standard colour and a rainbow, but nothing in between...:\
     
    imotionzz likes this.
  11. Offline

    stirante

    Haven't tested it. I only noticed this:
    Code:
                        else if (par1Str.equals("mobSpell"))
                        {
                            var21 = new EntitySpellParticleFX(this.theWorld, par2, par4, par6, 0.0D, 0.0D, 0.0D);
                            ((EntityFX)var21).setRBGColorF((float)par8, (float)par10, (float)par12);
                        }
                        else if (par1Str.equals("mobSpellAmbient"))
                        {
                            var21 = new EntitySpellParticleFX(this.theWorld, par2, par4, par6, 0.0D, 0.0D, 0.0D);
                            ((EntityFX)var21).setAlphaF(0.15F);
                            ((EntityFX)var21).setRBGColorF((float)par8, (float)par10, (float)par12);
                        }
    Where par8, par10 and par12 are:
    Code:
                double var9 = this.rand.nextGaussian() * (double)par1Packet63WorldParticles.func_98197_l();
                double var11 = this.rand.nextGaussian() * (double)par1Packet63WorldParticles.func_98197_l();
                double var13 = this.rand.nextGaussian() * (double)par1Packet63WorldParticles.func_98197_l();
    And this method from packet returns speed.
     
  12. Offline

    DSH105

    stirante
    Hmmm. I'll keep trying. There must be something that does it...
     
  13. Offline

    stirante

    I can give you code which process this packet.
     
  14. Offline

    DSH105

    Sure. Any help would be great :)
     
  15. Offline

    stirante

    Class Packet63WorldParticles:
    Code:
    package net.minecraft.src;
     
    import java.io.DataInputStream;
    import java.io.DataOutputStream;
    import java.io.IOException;
     
    public class Packet63WorldParticles extends Packet
    {
        private String field_98209_a;
        private float field_98207_b;
        private float field_98208_c;
        private float field_98205_d;
        private float field_98206_e;
        private float field_98203_f;
        private float field_98204_g;
        private float field_98210_h;
        private int field_98211_i;
     
        /**
        * Abstract. Reads the raw packet data from the data stream.
        */
        public void readPacketData(DataInputStream par1DataInputStream) throws IOException
        {
            this.field_98209_a = readString(par1DataInputStream, 64);
            this.field_98207_b = par1DataInputStream.readFloat();
            this.field_98208_c = par1DataInputStream.readFloat();
            this.field_98205_d = par1DataInputStream.readFloat();
            this.field_98206_e = par1DataInputStream.readFloat();
            this.field_98203_f = par1DataInputStream.readFloat();
            this.field_98204_g = par1DataInputStream.readFloat();
            this.field_98210_h = par1DataInputStream.readFloat();
            this.field_98211_i = par1DataInputStream.readInt();
        }
     
        /**
        * Abstract. Writes the raw packet data to the data stream.
        */
        public void writePacketData(DataOutputStream par1DataOutputStream) throws IOException
        {
            writeString(this.field_98209_a, par1DataOutputStream);
            par1DataOutputStream.writeFloat(this.field_98207_b);
            par1DataOutputStream.writeFloat(this.field_98208_c);
            par1DataOutputStream.writeFloat(this.field_98205_d);
            par1DataOutputStream.writeFloat(this.field_98206_e);
            par1DataOutputStream.writeFloat(this.field_98203_f);
            par1DataOutputStream.writeFloat(this.field_98204_g);
            par1DataOutputStream.writeFloat(this.field_98210_h);
            par1DataOutputStream.writeInt(this.field_98211_i);
        }
     
        public String func_98195_d()
        {
            return this.field_98209_a;
        }
     
        public double func_98200_f()
        {
            return (double)this.field_98207_b;
        }
     
        public double func_98194_g()
        {
            return (double)this.field_98208_c;
        }
     
        public double func_98198_h()
        {
            return (double)this.field_98205_d;
        }
     
        public float func_98196_i()
        {
            return this.field_98206_e;
        }
     
        public float func_98201_j()
        {
            return this.field_98203_f;
        }
     
        public float func_98199_k()
        {
            return this.field_98204_g;
        }
     
        public float func_98197_l()
        {
            return this.field_98210_h;
        }
     
        public int func_98202_m()
        {
            return this.field_98211_i;
        }
     
        /**
        * Passes this Packet on to the NetHandler for processing.
        */
        public void processPacket(NetHandler par1NetHandler)
        {
            par1NetHandler.func_98182_a(this);
        }
     
        /**
        * Abstract. Return the size of the packet (not counting the header).
        */
        public int getPacketSize()
        {
            return 64;
        }
    }
    Method which receives packet:
    Code:
     
        public void func_98182_a(Packet63WorldParticles par1Packet63WorldParticles)
        {
            for (int var2 = 0; var2 < par1Packet63WorldParticles.func_98202_m(); ++var2)
            {
                double var3 = this.rand.nextGaussian() * (double)par1Packet63WorldParticles.func_98196_i();
                double var5 = this.rand.nextGaussian() * (double)par1Packet63WorldParticles.func_98201_j();
                double var7 = this.rand.nextGaussian() * (double)par1Packet63WorldParticles.func_98199_k();
                double var9 = this.rand.nextGaussian() * (double)par1Packet63WorldParticles.func_98197_l();
                double var11 = this.rand.nextGaussian() * (double)par1Packet63WorldParticles.func_98197_l();
                double var13 = this.rand.nextGaussian() * (double)par1Packet63WorldParticles.func_98197_l();
                this.worldClient.spawnParticle(par1Packet63WorldParticles.func_98195_d(), par1Packet63WorldParticles.func_98200_f() + var3, par1Packet63WorldParticles.func_98194_g() + var5, par1Packet63WorldParticles.func_98198_h() + var7, var9, var11, var13);
            }
        }
    Code:
     
        /**
        * Spawns a particle.  Args particleName, x, y, z, velX, velY, velZ
        */
        public void spawnParticle(String par1Str, double par2, double par4, double par6, double par8, double par10, double par12)
        {
            for (int var14 = 0; var14 < this.worldAccesses.size(); ++var14)
            {
                ((IWorldAccess)this.worldAccesses.get(var14)).spawnParticle(par1Str, par2, par4, par6, par8, par10, par12);
            }
        }
    And methods from RenderGlobal:
    Code:
     
        /**
        * Spawns a particle. Arg: particleType, x, y, z, velX, velY, velZ
        */
        public void spawnParticle(String par1Str, double par2, double par4, double par6, double par8, double par10, double par12)
        {
            try
            {
                this.doSpawnParticle(par1Str, par2, par4, par6, par8, par10, par12);
            }
            catch (Throwable var17)
            {
                CrashReport var15 = CrashReport.makeCrashReport(var17, "Exception while adding particle");
                CrashReportCategory var16 = var15.makeCategory("Particle being added");
                var16.addCrashSection("Name", par1Str);
                var16.addCrashSectionCallable("Position", new CallableParticlePositionInfo(this, par2, par4, par6));
                throw new ReportedException(var15);
            }
        }
     
        /**
        * Spawns a particle. Arg: particleType, x, y, z, velX, velY, velZ
        */
        public EntityFX doSpawnParticle(String par1Str, double par2, double par4, double par6, double par8, double par10, double par12)
        {
            if (this.mc != null && this.mc.renderViewEntity != null && this.mc.effectRenderer != null)
            {
                int var14 = this.mc.gameSettings.particleSetting;
     
                if (var14 == 1 && this.theWorld.rand.nextInt(3) == 0)
                {
                    var14 = 2;
                }
     
                double var15 = this.mc.renderViewEntity.posX - par2;
                double var17 = this.mc.renderViewEntity.posY - par4;
                double var19 = this.mc.renderViewEntity.posZ - par6;
                EntityFX var21 = null;
     
                if (par1Str.equals("hugeexplosion"))
                {
                    this.mc.effectRenderer.addEffect(var21 = new EntityHugeExplodeFX(this.theWorld, par2, par4, par6, par8, par10, par12));
                }
                else if (par1Str.equals("largeexplode"))
                {
                    this.mc.effectRenderer.addEffect(var21 = new EntityLargeExplodeFX(this.renderEngine, this.theWorld, par2, par4, par6, par8, par10, par12));
                }
                else if (par1Str.equals("fireworksSpark"))
                {
                    this.mc.effectRenderer.addEffect(var21 = new EntityFireworkSparkFX(this.theWorld, par2, par4, par6, par8, par10, par12, this.mc.effectRenderer));
                }
     
                if (var21 != null)
                {
                    return (EntityFX)var21;
                }
                else
                {
                    double var22 = 16.0D;
     
                    if (var15 * var15 + var17 * var17 + var19 * var19 > var22 * var22)
                    {
                        return null;
                    }
                    else if (var14 > 1)
                    {
                        return null;
                    }
                    else
                    {
                        if (par1Str.equals("bubble"))
                        {
                            var21 = new EntityBubbleFX(this.theWorld, par2, par4, par6, par8, par10, par12);
                        }
                        else if (par1Str.equals("suspended"))
                        {
                            var21 = new EntitySuspendFX(this.theWorld, par2, par4, par6, par8, par10, par12);
                        }
                        else if (par1Str.equals("depthsuspend"))
                        {
                            var21 = new EntityAuraFX(this.theWorld, par2, par4, par6, par8, par10, par12);
                        }
                        else if (par1Str.equals("townaura"))
                        {
                            var21 = new EntityAuraFX(this.theWorld, par2, par4, par6, par8, par10, par12);
                        }
                        else if (par1Str.equals("crit"))
                        {
                            var21 = new EntityCritFX(this.theWorld, par2, par4, par6, par8, par10, par12);
                        }
                        else if (par1Str.equals("magicCrit"))
                        {
                            var21 = new EntityCritFX(this.theWorld, par2, par4, par6, par8, par10, par12);
                            ((EntityFX)var21).setRBGColorF(((EntityFX)var21).getRedColorF() * 0.3F, ((EntityFX)var21).getGreenColorF() * 0.8F, ((EntityFX)var21).getBlueColorF());
                            ((EntityFX)var21).setParticleTextureIndex(((EntityFX)var21).getParticleTextureIndex() + 1);
                        }
                        else if (par1Str.equals("smoke"))
                        {
                            var21 = new EntitySmokeFX(this.theWorld, par2, par4, par6, par8, par10, par12);
                        }
                        else if (par1Str.equals("mobSpell"))
                        {
                            var21 = new EntitySpellParticleFX(this.theWorld, par2, par4, par6, 0.0D, 0.0D, 0.0D);
                            ((EntityFX)var21).setRBGColorF((float)par8, (float)par10, (float)par12);
                        }
                        else if (par1Str.equals("mobSpellAmbient"))
                        {
                            var21 = new EntitySpellParticleFX(this.theWorld, par2, par4, par6, 0.0D, 0.0D, 0.0D);
                            ((EntityFX)var21).setAlphaF(0.15F);
                            ((EntityFX)var21).setRBGColorF((float)par8, (float)par10, (float)par12);
                        }
                        else if (par1Str.equals("spell"))
                        {
                            var21 = new EntitySpellParticleFX(this.theWorld, par2, par4, par6, par8, par10, par12);
                        }
                        else if (par1Str.equals("instantSpell"))
                        {
                            var21 = new EntitySpellParticleFX(this.theWorld, par2, par4, par6, par8, par10, par12);
                            ((EntitySpellParticleFX)var21).func_70589_b(144);
                        }
                        else if (par1Str.equals("witchMagic"))
                        {
                            var21 = new EntitySpellParticleFX(this.theWorld, par2, par4, par6, par8, par10, par12);
                            ((EntitySpellParticleFX)var21).func_70589_b(144);
                            float var24 = this.theWorld.rand.nextFloat() * 0.5F + 0.35F;
                            ((EntityFX)var21).setRBGColorF(1.0F * var24, 0.0F * var24, 1.0F * var24);
                        }
                        else if (par1Str.equals("note"))
                        {
                            var21 = new EntityNoteFX(this.theWorld, par2, par4, par6, par8, par10, par12);
                        }
                        else if (par1Str.equals("portal"))
                        {
                            var21 = new EntityPortalFX(this.theWorld, par2, par4, par6, par8, par10, par12);
                        }
                        else if (par1Str.equals("enchantmenttable"))
                        {
                            var21 = new EntityEnchantmentTableParticleFX(this.theWorld, par2, par4, par6, par8, par10, par12);
                        }
                        else if (par1Str.equals("explode"))
                        {
                            var21 = new EntityExplodeFX(this.theWorld, par2, par4, par6, par8, par10, par12);
                        }
                        else if (par1Str.equals("flame"))
                        {
                            var21 = new EntityFlameFX(this.theWorld, par2, par4, par6, par8, par10, par12);
                        }
                        else if (par1Str.equals("lava"))
                        {
                            var21 = new EntityLavaFX(this.theWorld, par2, par4, par6);
                        }
                        else if (par1Str.equals("footstep"))
                        {
                            var21 = new EntityFootStepFX(this.renderEngine, this.theWorld, par2, par4, par6);
                        }
                        else if (par1Str.equals("splash"))
                        {
                            var21 = new EntitySplashFX(this.theWorld, par2, par4, par6, par8, par10, par12);
                        }
                        else if (par1Str.equals("largesmoke"))
                        {
                            var21 = new EntitySmokeFX(this.theWorld, par2, par4, par6, par8, par10, par12, 2.5F);
                        }
                        else if (par1Str.equals("cloud"))
                        {
                            var21 = new EntityCloudFX(this.theWorld, par2, par4, par6, par8, par10, par12);
                        }
                        else if (par1Str.equals("reddust"))
                        {
                            var21 = new EntityReddustFX(this.theWorld, par2, par4, par6, (float)par8, (float)par10, (float)par12);
                        }
                        else if (par1Str.equals("snowballpoof"))
                        {
                            var21 = new EntityBreakingFX(this.theWorld, par2, par4, par6, Item.snowball);
                        }
                        else if (par1Str.equals("dripWater"))
                        {
                            var21 = new EntityDropParticleFX(this.theWorld, par2, par4, par6, Material.water);
                        }
                        else if (par1Str.equals("dripLava"))
                        {
                            var21 = new EntityDropParticleFX(this.theWorld, par2, par4, par6, Material.lava);
                        }
                        else if (par1Str.equals("snowshovel"))
                        {
                            var21 = new EntitySnowShovelFX(this.theWorld, par2, par4, par6, par8, par10, par12);
                        }
                        else if (par1Str.equals("slime"))
                        {
                            var21 = new EntityBreakingFX(this.theWorld, par2, par4, par6, Item.slimeBall);
                        }
                        else if (par1Str.equals("heart"))
                        {
                            var21 = new EntityHeartFX(this.theWorld, par2, par4, par6, par8, par10, par12);
                        }
                        else if (par1Str.equals("angryVillager"))
                        {
                            var21 = new EntityHeartFX(this.theWorld, par2, par4 + 0.5D, par6, par8, par10, par12);
                            ((EntityFX)var21).setParticleTextureIndex(81);
                            ((EntityFX)var21).setRBGColorF(1.0F, 1.0F, 1.0F);
                        }
                        else if (par1Str.equals("happyVillager"))
                        {
                            var21 = new EntityAuraFX(this.theWorld, par2, par4, par6, par8, par10, par12);
                            ((EntityFX)var21).setParticleTextureIndex(82);
                            ((EntityFX)var21).setRBGColorF(1.0F, 1.0F, 1.0F);
                        }
                        else if (par1Str.startsWith("iconcrack_"))
                        {
                            int var27 = Integer.parseInt(par1Str.substring(par1Str.indexOf("_") + 1));
                            var21 = new EntityBreakingFX(this.theWorld, par2, par4, par6, par8, par10, par12, Item.itemsList[var27]);
                        }
                        else if (par1Str.startsWith("tilecrack_"))
                        {
                            String[] var28 = par1Str.split("_", 3);
                            int var25 = Integer.parseInt(var28[1]);
                            int var26 = Integer.parseInt(var28[2]);
                            var21 = (new EntityDiggingFX(this.theWorld, par2, par4, par6, par8, par10, par12, Block.blocksList[var25], 0, var26)).func_90019_g(var26);
                        }
     
                        if (var21 != null)
                        {
                            this.mc.effectRenderer.addEffect((EntityFX)var21);
                        }
     
                        return (EntityFX)var21;
                    }
                }
            }
            else
            {
                return null;
            }
        }
    
    Here are for example constructors from EntityNoteFX:
    Code:
     
        public EntityNoteFX(World par1World, double par2, double par4, double par6, double par8, double par10, double par12)
        {
            this(par1World, par2, par4, par6, par8, par10, par12, 2.0F);
        }
     
        public EntityNoteFX(World par1World, double par2, double par4, double par6, double par8, double par10, double par12, float par14)
        {
            super(par1World, par2, par4, par6, 0.0D, 0.0D, 0.0D);
            this.motionX *= 0.009999999776482582D;
            this.motionY *= 0.009999999776482582D;
            this.motionZ *= 0.009999999776482582D;
            this.motionY += 0.2D;
            this.particleRed = MathHelper.sin(((float)par8 + 0.0F) * (float)Math.PI * 2.0F) * 0.65F + 0.35F;
            this.particleGreen = MathHelper.sin(((float)par8 + 0.33333334F) * (float)Math.PI * 2.0F) * 0.65F + 0.35F;
            this.particleBlue = MathHelper.sin(((float)par8 + 0.6666667F) * (float)Math.PI * 2.0F) * 0.65F + 0.35F;
            this.particleScale *= 0.75F;
            this.particleScale *= par14;
            this.noteParticleScale = this.particleScale;
            this.particleMaxAge = 6;
            this.noClip = false;
            this.setParticleTextureIndex(64);
        }[/code}
     
    microgeek and _DSH105_ like this.
  16. Offline

    DarkBladee12

    microgeek Just a tip: You could use reflection to get the Packet63WorldParticles and the .sendPacket so your api would be update-proof. I already did that by myself, you can message me if you want the code ;)
     
  17. Offline

    DSH105

    I did that here as well :). It's not too hard if you have got the hang of reflection.

    Code:java
    1.  
    2. Method getHandle = p.getClass().getMethod("getHandle");
    3. Object nmsPlayer = getHandle.invoke(p);
    4. Field con_field = nmsPlayer.getClass().getField("playerConnection");
    5. Object con = con_field.get(nmsPlayer);
    6. Method packet_method = ReflectionUtil.getMethod(con.getClass(), "sendPacket");
    7. packet_method.invoke(con, packet);
    8.  
     
  18. Offline

    DarkBladee12

    _DSH105_ Yeah, but you should get the packet through reflection too, because packets are only in the nms package^^
     
  19. Offline

    DSH105

    DarkBladee12
    Code:java
    1.  
    2.  
    3. Object packet = Class.forName("net.minecraft.server" + v + ".Packet63WorldParticles").getConstructor().newInstance();
    4.  
     
  20. Offline

    ohtwo

    Where have you added this code to? :eek:
     
  21. Offline

    DSH105

    It hasn't been changed at all (not even "happerVillager" has been fixed yet).

    microgeek - Your thread needs updating.
     
  22. Offline

    ohtwo

    Ah okay, I thought maybe I missed something. Thanks. I'm guessing the theoretical "play at location" method is a lot better than just sending the packet to all players?
     
  23. Offline

    Minnymin3

    _DSH105_
    How did you make this update-proof? Im trying to figure out java reflection but I can't seem to get it...
     
  24. Offline

    DSH105

    It just takes a bit of practice and time to get the correct methods needed. It helps sometimes if you write it version-dependent first and then convert it.
     
  25. Offline

    DarkBladee12

    Minnymin3 This is my update-proof version:

    Code:
    import java.lang.reflect.Field;
    import java.lang.reflect.Method;
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    import java.util.Map.Entry;
     
    import org.bukkit.Bukkit;
    import org.bukkit.Location;
    import org.bukkit.entity.Player;
     
    public enum ParticleEffect {
     
        HUGE_EXPLOSION("hugeexplosion", 0), LARGE_EXPLODE("largeexplode", 1), FIREWORKS_SPARK("fireworksSpark", 2), BUBBLE("bubble", 3), SUSPEND("suspend", 4), DEPTH_SUSPEND("depthSuspend", 5), TOWN_AURA("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("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("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("snowshovel", 28), SLIME("slime", 29), HEART("heart", 30), ANGRY_VILLAGER("angryVillager", 31), HAPPY_VILLAGER("happyVillager", 32), ICONCRACK("iconcrack", 33), TILECRACK("tilecrack", 34);
     
        private String name;
        private int id;
     
        ParticleEffect(String name, int id) {
            this.name = name;
            this.id = id;
        }
     
        public String getName() {
            return name;
        }
     
        public int getId() {
            return id;
        }
     
        private static final Map<String, ParticleEffect> NAME_MAP = new HashMap<String, ParticleEffect>();
        private static final Map<Integer, ParticleEffect> ID_MAP = new HashMap<Integer, ParticleEffect>();
        static {
            for (ParticleEffect effect : values()) {
                NAME_MAP.put(effect.name, effect);
                ID_MAP.put(effect.id, effect);
            }
        }
     
        public static ParticleEffect fromName(String name) {
            if (name == null) {
                return null;
            }
            for (Entry<String, ParticleEffect> e : NAME_MAP.entrySet()) {
                if (e.getKey().equalsIgnoreCase(name)) {
                    return e.getValue();
                }
            }
            return null;
        }
     
        public static ParticleEffect fromId(int id) {
            return ID_MAP.get(id);
        }
     
        public static String getDetailedList() {
            List<String> list = new ArrayList<String>();
            for (String name : NAME_MAP.keySet()) {
                list.add(name + "§7, §8" + NAME_MAP.get(name).getId());
            }
            return new GeneralUtil().getDetailedList(list);
        }
     
        public static void sendToPlayer(ParticleEffect effect, Player player, Location location, float offsetX, float offsetY, float offsetZ, float speed, int count) throws Exception {
            Object packet = createPacket(effect, location, offsetX, offsetY, offsetZ, speed, count);
            sendPacket(player, packet);
        }
     
        public static void sendToLocation(ParticleEffect effect, Location location, float offsetX, float offsetY, float offsetZ, float speed, int count) throws Exception {
            Object packet = createPacket(effect, location, offsetX, offsetY, offsetZ, speed, count);
            for (Player player : Bukkit.getOnlinePlayers()) {
                sendPacket(player, packet);
            }
        }
     
        public static void sendCrackToPlayer(boolean icon, int id, byte data, Player player, Location location, float offsetX, float offsetY, float offsetZ, int count) throws Exception {
            Object packet = createCrackPacket(icon, id, data, location, offsetX, offsetY, offsetZ, count);
            sendPacket(player, packet);
        }
     
        public static void sendCrackToLocation(boolean icon, int id, byte data, Location location, float offsetX, float offsetY, float offsetZ, int count) throws Exception {
            Object packet = createCrackPacket(icon, id, data, location, offsetX, offsetY, offsetZ, count);
            for (Player player : Bukkit.getOnlinePlayers()) {
                sendPacket(player, packet);
            }
        }
     
        public static Object createPacket(ParticleEffect effect, Location location, float offsetX, float offsetY, float offsetZ, float speed, int count) throws Exception {
            if (count <= 0)
                count = 1;
            Object packet = getPacket63WorldParticles();
            setValue(packet, "a", effect.name);
            setValue(packet, "b", (float) location.getX());
            setValue(packet, "c", (float) location.getY());
            setValue(packet, "d", (float) location.getZ());
            setValue(packet, "e", offsetX);
            setValue(packet, "f", offsetY);
            setValue(packet, "g", offsetZ);
            setValue(packet, "h", speed);
            setValue(packet, "i", count);
            return packet;
        }
     
        public static Object createCrackPacket(boolean icon, int id, byte data, Location location, float offsetX, float offsetY, float offsetZ, int count) throws Exception {
            if (count <= 0)
                count = 1;
            Object packet = getPacket63WorldParticles();
            String modifier = "iconcrack_" + id;
            if (!icon) {
                modifier = "tilecrack_" + id + "_" + data;
            }
            setValue(packet, "a", modifier);
            setValue(packet, "b", (float) location.getX());
            setValue(packet, "c", (float) location.getY());
            setValue(packet, "d", (float) location.getZ());
            setValue(packet, "e", offsetX);
            setValue(packet, "f", offsetY);
            setValue(packet, "g", offsetZ);
            setValue(packet, "h", 0.1F);
            setValue(packet, "i", count);
            return packet;
        }
     
        private static void setValue(Object instance, String fieldName, Object value) throws Exception {
            Field field = instance.getClass().getDeclaredField(fieldName);
            field.setAccessible(true);
            field.set(instance, value);
        }
     
        private static Object getEntityPlayer(Player p) throws Exception {
            Method getHandle = p.getClass().getMethod("getHandle");
            return getHandle.invoke(p);
        }
     
        private static String getPackageName() {
            return "net.minecraft.server." + Bukkit.getServer().getClass().getPackage().getName().replace(".", ",").split(",")[3];
        }
     
        private static Object getPacket63WorldParticles() throws Exception {
            Class<?> packet = Class.forName(getPackageName() + ".Packet63WorldParticles");
            return packet.getConstructors()[0].newInstance();
        }
     
        private static void sendPacket(Player p, Object packet) throws Exception {
            Object eplayer = getEntityPlayer(p);
            Field playerConnectionField = eplayer.getClass().getField("playerConnection");
            Object playerConnection = playerConnectionField.get(eplayer);
            for (Method m : playerConnection.getClass().getMethods()) {
                if (m.getName().equalsIgnoreCase("sendPacket")) {
                    m.invoke(playerConnection, packet);
                    return;
                }
            }
        }
    }
    
     
  26. Offline

    Zarius

    DarkBladee12 - that looks cool :) Mind if I use it?

    Also, is there anywhere that documents the effect of speed (does this just make the effect play faster?) & offset (just a standard location offset?) on the effects or just trial and error?
     
  27. Offline

    ohtwo

    Does the normal sendToLocation method provided by Bukkit actually send the particle to all players, or does it send it to players within a certain bound? It's probably more efficient to do the latter if that's how Bukkit handles it.
     
  28. Offline

    Minnymin3

    Wow nice! I had figured it out after half an hour of fiddling and testing
     
  29. Offline

    DarkBladee12

    Zarius You can use it any time you want ;) The speed makes some particle effects play faster, but not all are affected by the speed! I always use "new Random().nextFloat()" for the offset values in order to let it look natural.

    ohtwo The sendToLocation method in my version just sends the particle effect to all players.

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: May 31, 2016
  30. Offline

    Andrewsnowfalls

Thread Status:
Not open for further replies.

Share This Page