On entity damage show randomly coloured particles

Discussion in 'Plugin Development' started by TheMintyMate, Apr 7, 2014.

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

    TheMintyMate

    Ive recently finished developing a kit plugin which uses lightning, and ive received a few suggestions of how I could add to/change the plugin, and one suggestion which I cant squash is showing randomly coloured particles around a player when they take damage. From what I have gathered, I may need to use packets, but I'm not sure.
    Any help is greatly appreciated :)
     
  2. Offline

    Zethariel

  3. You could use ProtocolLib (yes, packets) and then look at this thread:
    http://dev.bukkit.org/bukkit-plugins/protocollib/forum/61834-particle-effects/#p4

    What Zethariel said would also work, probably better as it does not have so many extra features and does not depend on a plugin that has bugs. If you merge what aadnk said with that particle packet library for the coloured effects, it would work.

    Edit: Found an issue with the Particle Packet Library; It does not use 100% reflection meaning that you'd have to update the plugin every bukkit version - I dislike this very much but apparently it's for the best - getting rid of the lazy developers.

    Edit 2: Found a version-proof method on page 2: https://forums.bukkit.org/threads/particle-packet-library.138493/page-2
    DarkBladee12's comment.

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: Jun 7, 2016
  4. Offline

    TheMintyMate

    KingFaris11
    Zethariel
    Ok thanks :) I'm looking at the thread...

    KingFaris11
    Zethariel
    How do I integrate and use the packet?
    Also, how will I influence the colour of the particles?
    Thanks :)

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: Jun 7, 2016
  5. I'm not sure how you can influence the colour of the particles with Zethariel's comment, but with the one I posted of ProtocolLib, aadnk's comment tells you how to.
    Code:
    particles.setParticleName("blockdust_" + Material.WOOL.getId() + "_" + 13); // green
    // particles.setParticleName("blockdust_" + Material.WOOL.getId() + "_" + 11); // blue
    // particles.setParticleName("blockdust_" + Material.WOOL.getId() + "_" + 4); // green
    
    It uses the colour of the wool (data value).

    You implement this into EntityDamageEvent, if event.getEntityType() is EntityType.PLAYER and if event.getCause() is equal to DamageCause.LIGHTNING, spawn the particle effects.
     
    TheMintyMate likes this.
  6. Offline

    TheMintyMate

    KingFaris11
    ok..... I'm now working on it :) Il be back with progress shortly.

    KingFaris11
    Ok, here is my current progress:
    Code:
    @EventHandler
    public void entityDamageEvent(EntityDamageEvent event){
     if ( event.getEntityType() == EntityType.PLAYER){
      particles.setParticleName("blockdust_" + Material.WOOL.getId() + "_" + 13); 
     }
    }
    
    S0, how do I implement the packet so particles.setParticlName can be resolved?

    KingFaris11
    UPDATE
    Code:
    @SuppressWarnings("deprecation")
    @EventHandler
    public void entityDamageEvent(EntityDamageEvent event){
     if ( event.getEntityType() == EntityType.PLAYER){
      Player player = player.getPlayer();
      player.playSound(player.getLocation(), Sound.FIRE_IGNITE, 1, 0);
      particles.setParticleName("blockdust_" + Material.WOOL.getId() + "_" + 13); 
     }
    }
    
    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: Jun 7, 2016
  7. Sorry, was at swimming. Okay, you did it wrong xD

    Code:
    if (event.getEntityType() == EntityType.PLAYER && event.getCause() == DamageCause.LIGHTNING) {
        Player player = (Player) event.getPlayer();
        player.playSound(player.getLocation(), Sound.FIRE_IGNITE, 1F, 1F);
        WrapperPlayServerWorldParticles particles = new WrapperPlayServerWorldParticles();
        particles.setNumberOfParticles(5);
        particles.setOffsetX(1);
        particles.setOffsetZ(1);
        particles.setOffsetY(1);
        particles.setLocation(player.getLocation());
        particles.setParticleName("blockdust_" + Material.WOOL.getId() + "_" + 13);
        particles.sendPacket(player);
    }
    
    Note: This code makes it so only the player can see the particle effects.
    If you want to make it so all players on the server can see the particle effects played at the player's location, instead of:
    Code:
    particles.sendPacket(player);
    Use:
    Code:
    for (Player onlinePlayer : player.getServer().getOnlinePlayers()) {
        particles.sendPacket(onlinePlayer);
    }
    
     
    TheMintyMate likes this.
  8. Offline

    TheMintyMate

    KingFaris11
    Ok, Almost all good. I'm now just getting an error at:
    Code:
    WrapperPlayServerWorldParticles particles = new WrapperPlayServerWorldParticles();
    
    This is because the "WrapperPlayServerWorldParticles" and "new WrapperPlayServerWorldParticles()" cannot be resolved to a type. S0, what do I do here?
    My enum contains the following (Note: my enum contains no errors]:
    Code:
    package com.-----------------------------------------;
    import java.lang.reflect.Field;
    import java.lang.reflect.Method;
    import java.util.HashMap;
    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 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;
                }
            }
        }
    }
     
    
    Thanks for all you help :)

    Edit: How was swimming? xD
     
Thread Status:
Not open for further replies.

Share This Page