Util [NMS]Make Animals show love particles!

Discussion in 'Resources' started by mine-care, Jan 22, 2015.

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

    mine-care

    Hello there fellow plugin developers!
    I have seen in the past a thread asking how to make animals display hearts (usually shown when you offer them food and they are ready to bread) I wondered the same while making a pets plugin for my server, and i came up with this solution that i wanted to share with you because i assume other people will have this question too, (especially pet plugin developers can use this as a way for the pets to express their love for their owners)
    So, there is the simple but Version-Dependend way (if you use this, it is more efficient but when server's build changes, imports have to be updated to a version matching the one server has)
    Code:
        private void playEntityLove(Entity e, Player player) {
            if (!(e instanceof Animals))throw new IllegalArgumentException(
                        "Monsters/players cannot show love! <3");
            //Constructing the packet
            PacketPlayOutEntityStatus EntityStatus = new PacketPlayOutEntityStatus(((CraftEntity)e).getHandle(), (byte) 18);
            //Checking players distance (particles are visible up to 16 blocks away, no reason to sent a packet to a player >16 blocks away)
            if (Math.floor(player.getLocation().distance(e.getLocation())) <= 16) {
                //Sending the packet to player.
                ((CraftPlayer) player).getHandle().playerConnection.sendPacket(EntityStatus);
            }
        }
    The Version-Independend method that uses refection (this method will work no matter if the server's version matches the one used to compile the plugin for as long as the server has the nessesary classes)
    Code:
    private void playEntityLoveVersionIndepended(Entity e,Player to){
            if (!(e instanceof Animals))throw new IllegalArgumentException("Monsters/players cannot show love! <3");
            String bukkitVersion = Bukkit.getServer().getClass().getPackage().getName().substring(23);
            if(Math.floor(to.getLocation().distance(e.getLocation()))<=16){
                try{
                //Getting the packet's class
                Class<?> entityStatusPacket = Class.forName("net.minecraft.server."+bukkitVersion+".PacketPlayOutEntityStatus");
                //Getting packet's superclass (see playerConnection
                Class<?> packet = Class.forName("net.minecraft.server." + bukkitVersion + ".Packet");
                //Get craftplayer's class for casting later on
                Class<?> craftPlayer = Class.forName("org.bukkit.craftbukkit." +  bukkitVersion + ".entity.CraftPlayer");
                //Getting the net minecraft server's entity since its needed for the constructor of the packet
                Class<?> nmsEntity = Class.forName("net.minecraft.server."+bukkitVersion+".Entity");
                //Getting CraftEntity class to retrieve the getHandle method from
                Class<?> nmsCraftEntity = Class.forName("org.bukkit.craftbukkit."+bukkitVersion+".entity.CraftEntity");
                //Getting the "getHandle()" method that returns Entity (nms Entity)
                Method entityhandle = nmsCraftEntity.getMethod("getHandle", null);
                //Building the constructor of the packet
                Constructor<?> entityStatusConstructor = entityStatusPacket.getDeclaredConstructor(new Class[]{nmsEntity,byte.class});
                //turning the classes above to usable objects
                Object nmsEntityObject = nmsCraftEntity.cast(e);
                Object nmsEntitys = entityhandle.invoke(nmsEntityObject, null);
                Object entityStatusPacketObj = entityStatusConstructor.newInstance(new Object[]{nmsEntitys,(byte)18});
                Object cp = craftPlayer.cast(to);
                Object handle = craftPlayer.getMethod("getHandle").invoke(cp);
                Object playerConnection = handle.getClass().getField("playerConnection").get(handle);
                //sending the packet (yay!)
                playerConnection.getClass().getMethod("sendPacket", packet).invoke(playerConnection, entityStatusPacketObj);
                }catch( IllegalAccessException | IllegalArgumentException | InvocationTargetException |
                        ClassNotFoundException | InstantiationException | NoSuchMethodException |
                        SecurityException | NoSuchFieldException ex){
                    ex.printStackTrace();
                }
            }
        }
    A note about this method, i havent used reflection for quite some time so i might be a bit rusty and have some mistakes. If you trace them please let me know! =D

    Hope you found this thread usefull <3
    Please point out any kind of fixes that should be done!
     
    ChipDev and DJSkepter like this.
  2. Offline

    ChipDev

    I really love that you put commits everywhere <3
     
    mine-care likes this.
  3. Offline

    mine-care

    @ChipDev =D yay my first comment! Ehm back in topic :p thanks! i did it so people who like copy paste code (something i am completely against but who cares) will actually have the chance to understand roughly what goes on.
    Again thanks =D
     
    ChipDev likes this.
Thread Status:
Not open for further replies.

Share This Page