Library [CLASS] Mob Disguise! [1.8 support!]

Discussion in 'Resources' started by mine-care, Mar 15, 2015.

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

    mine-care

    Hello there!
    The last days i have been working with disguising a player as a mob.
    So i made a library to share with you =D
    it requiers this reflection util class
    (credit to @DarkBladee12)
    And the class itself:
    Code:
    package com.fillpant.itemremove;
    
    import org.bukkit.Bukkit;
    import org.bukkit.entity.Player;
    import org.bukkit.inventory.ItemStack;
    
    import com.fillpant.itemremove.ReflectionUtils.PackageType;
    
    /**
    * @author fillpant, Blame him!
    *
    */
    public class MyDisguise {
        private static final String bukkitversion = Bukkit.getServer().getClass()
                .getPackage().getName().substring(23);
        private String customName;
        private EntityDisguise type;
        private Player disguised;
        private ItemStack hand, helm, chst, leg, boot;
    
        /**
         * @param p
         *            player to disguise
         * @param type
         *            Entity type of disguise
         */
        public MyDisguise(Player p, EntityDisguise type) {
            this(p, type, null);
        }
    
        /**
         * @param p
         *            player to disguise
         * @param type
         *            Entity type of disguise
         * @param name
         *            the display name of the disguised player (chat color is
         *            supported)
         */
        public MyDisguise(Player p, EntityDisguise type, String name) {
            this(p, type, name, null, null, null, null, null);
        }
    
        /**
         * @param p
         *            player to disguise
         * @param type
         *            Entity type of disguise
         * @param name
         *            the display name of the disguised player (chat color is
         *            supported)
         * @param inhand
         *            Item in hand
         * @param helmet
         *            helmet item
         * @param chestplate
         *            chestplate armor item
         * @param leggings
         *            leggings armor item
         * @param boots
         *            boots armor item <b>If You dont want a armor item like boots
         *            or something, provide 'null'</b>
         */
        public MyDisguise(Player p, EntityDisguise type, String name,
                ItemStack inhand, ItemStack helmet, ItemStack chestplate,
                ItemStack leggings, ItemStack boots) {
            this.customName = name;
            this.type = type;
            this.disguised = p;
            this.hand = inhand;
            this.helm = helmet;
            this.chst = chestplate;
            this.leg = leggings;
            this.boot = boots;
        }
    
        /**
         * @param to
         *            Player that will see the disguise (where the packets will be
         *            sent to.)
         * @throws Exception
         *             Many exceptions can occur due to reflection used.
         */
        public void sendDisguise(Player to) throws Exception {
            if (to.equals(disguised))
                throw new IllegalArgumentException(
                        "Target Player cannot be the same as the disguised player");
            Object packetplayoutentitydestroy = ReflectionUtils.instantiateObject(
                    "PacketPlayOutEntityDestroy", PackageType.MINECRAFT_SERVER,
                    new int[] { disguised.getEntityId() });
            Object world = ReflectionUtils.invokeMethod(disguised.getWorld(),
                    "getHandle", null);
            Class<?> entity = Class.forName(type.getClassName());
            Object ent = ReflectionUtils.instantiateObject(entity, world);
            ReflectionUtils.invokeMethod(ent, "setPosition", disguised
                    .getLocation().getX(), disguised.getLocation().getY(),
                    disguised.getLocation().getZ());
            ReflectionUtils.getMethod(entity, "d", int.class).invoke(ent,
                    disguised.getEntityId());
            if (customName != null) {
                ReflectionUtils.getMethod(entity, "setCustomName", String.class)
                        .invoke(ent, customName);
                ReflectionUtils.getMethod(entity, "setCustomNameVisible",
                        boolean.class).invoke(ent, true);
            }
            handleSpecialTypes(type, ent);
            Object packetplayoutspawnentityliving = ReflectionUtils
                    .instantiateObject("PacketPlayOutSpawnEntityLiving",
                            PackageType.MINECRAFT_SERVER, ent);
    
            sendPacket(to, packetplayoutentitydestroy);
            sendPacket(to, packetplayoutspawnentityliving);
            if (hand != null)
                sendArmorContentPackets(to, disguised.getEntityId(), 0, hand);
            if (helm != null)
                sendArmorContentPackets(to, disguised.getEntityId(), 1, helm);
            if (chst != null)
                sendArmorContentPackets(to, disguised.getEntityId(), 2, chst);
            if (leg != null)
                sendArmorContentPackets(to, disguised.getEntityId(), 3, leg);
            if (boot != null)
                sendArmorContentPackets(to, disguised.getEntityId(), 4, boot);
    
        }
    
        /**
         * @param players
         *            players that will see the disguise happening. The rest will
         *            see the disguised player as player...
         */
        private void sendDisguise(Player... players) {
            for (Player P : players) {
                if (P.equals(disguised))
                    continue;
                try {
                    sendDisguise(P);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    
        /**
         * @param forwho
         *            who will see this update?
         * @throws Exception
         *             Reflection exceptions
         */
        public void updateDisguise(Player forwho) throws Exception {
            sendDisguise(forwho);
        }
    
        /**
         * @param players
         *            a array of players that will see the update
         */
        public void updateDisguise(Player... players) {
            sendDisguise(players);
        }
    
        /**
         * @param type
         *            the new Disguise type
         * @param sendto
         *            the player who will see the change
         * @throws Exception
         *             Reflection exceptions
         */
        public void changePlayerDisguise(EntityDisguise type, Player sendto)
                throws Exception {
            this.type = type;
            sendDisguise(sendto);
        }
    
        /*
         * @param type the new Disguise type
         *
         * @param sendto the player who will see the change
         *
         * @throws Exception Reflection exceptions
         */
        public void changePlayerDisguise(EntityDisguise type, Player... sendto)
                throws Exception {
            this.type = type;
            sendDisguise(sendto);
        }
    
        //Dont mind this
        private void sendPacket(Player p, Object pack) throws Exception {
            Class<?> packet = Class.forName("net.minecraft.server." + bukkitversion
                    + ".Packet");
            Class<?> craftPlayer = Class.forName("org.bukkit.craftbukkit."
                    + bukkitversion + ".entity.CraftPlayer");
            Object handle = craftPlayer.getMethod("getHandle").invoke(p);
            Object con = handle.getClass().getField("playerConnection").get(handle);
            con.getClass().getMethod("sendPacket", packet).invoke(con, pack);
        }
        //Dont mind this too.
        private void sendArmorContentPackets(Player to, int entityID, int slot,
                ItemStack item) throws Exception {
            PackageType type;
            if (bukkitversion.startsWith("v1_7_"))
                type = PackageType.CRAFTBUKKIT;
            else
                type = PackageType.CRAFTBUKKIT_INVENTORY;
            Object craftitmstk = ReflectionUtils.getMethod("CraftItemStack", type,
                    "asNMSCopy", item.getClass()).invoke(null, item);
            Object metadarapacket = ReflectionUtils.instantiateObject(
                    "PacketPlayOutEntityEquipment", PackageType.MINECRAFT_SERVER,
                    entityID, slot, craftitmstk);
            sendPacket(to, metadarapacket);
        }
    
        //Forget this as well :3
        private Object handleSpecialTypes(EntityDisguise type, Object entity)
                throws Exception {
            switch (type) {
            case WITHER_SKELETON:
                ReflectionUtils.invokeMethod(entity, "setSkeletonType", 1);
                break;
            }
            return entity;
        }
        /*To be documented,*/
        public ItemStack getItemInHand() {
            return hand;
        }
    
        public void setItemInHand(ItemStack hand) {
            this.hand = hand;
        }
    
        public ItemStack getHelmet() {
            return helm;
        }
    
        public void setHelmet(ItemStack helm) {
            this.helm = helm;
        }
    
        public ItemStack getChestplate() {
            return chst;
        }
    
        public void setChestplate(ItemStack chst) {
            this.chst = chst;
        }
    
        public ItemStack getLeggings() {
            return leg;
        }
    
        public void setLeggings(ItemStack leg) {
            this.leg = leg;
        }
    
        public ItemStack getBoots() {
            return boot;
        }
    
        public void setBoots(ItemStack boot) {
            this.boot = boot;
        }
    
        public String getCustomName() {
            return customName;
        }
    
        public void setCustomName(String customName) {
            this.customName = customName;
        }
    
        public EntityDisguise getType() {
            return type;
        }
    
        public void setType(EntityDisguise type) {
            this.type = type;
        }
    
        public Player getDisguised() {
            return disguised;
        }
    }
    
    /**
    *@author fillpant, Blame him!
    */
    enum EntityDisguise {
        ZOMBIE("EntityZombie"), WITHER_SKELETON("EntitySkeleton"), SKELETON(
                "EntitySkeleton"), ZOMBIEPIG("EntityPigZombie"), BLAZE(
                "EntityBlaze"), ENDERMAN("EntityEnderman"), CREEPER("EntityCreeper"), SPIDER(
                "EntitySpider"), WITCH("EntityWitch"), WITHER_BOSS("EntityWither"), GHAST(
                "EntityGhast"), GIANT("EntityGiantZombie"), SLIME("EntitySlime"), CAVE_SPIDER(
                "EntityCaveSpider"), SILVERFISH("EntitySilverfish"), MAGMA_CUBE(
                "EntityMagmaCube"), BAT("EntityBat"), PIG("EntityPig"), SHEEP(
                "EntitySheep"), COW("EntityCow"), CHICKEN("EntityChicken"), SQUID(
                "EntitySquid"), WOLF("EntityWolf"), OCELOT("EntityOcelot"), HORSE(
                "EntityHorse"), VILLAGER("EntityVillager"), IRON_GOLEM(
                "EntityIronGolem"), SNOWMAN("EntitySnowman"), ENDER_DRAGON(
                "EntityEnderDragon"), MOOSHROOM("EntityMushroomCow");
        private final String cls;
    
        EntityDisguise(String cls) {
            this.cls = cls;
        }
    
        /**
         * <b><u>FORGET THIS! DONT USE IT!</u></b>
         * @return
         */
        public String getClassName() {
            return "net.minecraft.server."
                    + Bukkit.getServer().getClass().getPackage().getName()
                            .substring(23) + "." + cls;
        }
    }
    
    How to use - Example usage:
    Code:
            new MyDisguise(e.getPlayer(), EntityDisguise.BLAZE,ChatColor.AQUA+"Blaze!",
                    new ItemStack(Material.DIAMOND_SWORD),null,null,null,null)
            .sendDisguise(Bukkit.getOnlinePlayers());
    Update #1
    After @DJSkepter 's correction, i forgot to add a "remove disguise" method, so here is the method:
    Code:
        public void removeDisguise() throws ReflectiveOperationException {
            Object ppoed = ReflectionUtils.instantiateObject(
                    "PacketPlayOutEntityDestroy", PackageType.MINECRAFT_SERVER,
                    new int[] { disguised.getEntityId() });
            Object ppones = ReflectionUtils.instantiateObject(
                    "PacketPlayOutNamedEntitySpawn", PackageType.MINECRAFT_SERVER,
                    ReflectionUtils.invokeMethod(disguised, "getHandle", null));
            for (Player p : Bukkit.getOnlinePlayers()) {
                if(p.equals(disguised)) continue;
                sendPacket(p, ppoed);
                sendPacket(p, ppones);
            }
        }

    Please let me know if you need any aditional features! <3 i would love to hear!
    Thanks for reading!

    PS i finished this at 3am so please point out any mistakes...
     
    Last edited: Jul 19, 2015
    The__Master_Coder and ChipDev like this.
  2. Offline

    DJSkepter

    @mine-care If you're using reflection, why does this topic say NMS?
     
  3. Offline

    mine-care

    @DJSkepter :eek: that was a fast comment! sorri i wanted to put [CLASS] to indicate it is not an external lib but a class, im fixing it :# ty!
     
    DJSkepter likes this.
  4. Offline

    DJSkepter

    @mine-care Apart from that, this looks awesome. I'm definitely going to use this in the future :D

    EDIT: How do you undisguise a player?
     
    Last edited: Mar 15, 2015
    mine-care likes this.
  5. Offline

    Totom3

    public void sendDisguise(Player to) throws Exception

    Please no. We all know reflection exceptions are not going to happen, so I suggest you just catch them. If you don't catch them, at least declare your method as one that throws ReflectiveOperationException, but NOT Exception. I also suggest you cache the methods and constructors needed to send the packet, as it'll speed up the process by a lot. Also setType() will accept a null EntityDisguise, you probably should check that. Finally it looks very practical, good job on that!
     
    mine-care likes this.
  6. Offline

    axeldu18

    Work with 1.8 ?

    EDIT: Yes thanks you very much ! :D
     
    Last edited: Mar 15, 2015
  7. Offline

    Funnygatt

    Your example says "new DaDisguise(e.getPlayer() etc.", but in the class, "DaDisguise" is nowhere to be found. Guessing this is a mistake or I just can't read :p
     
  8. Offline

    mine-care

    @DJSkepter oh right! i forgot the undisguise part that will turn the player back to human entity :O ty!

    @Totom3 i agree on the cacheing, but about reflection exceptions they are left for the user to handle since they may occu in bukkit by lets say a change on a field's name. Other than that ill static-fy the standard used fields and stuff, although it is just a few of them or else ill have to handle exceptions myself, tht i dont like... Ty!

    PS. you are right the al in one exception class is a litle (well not just a litlbe....) bad as a method.

    @Funnygatt Jep it says MyDisguise but thats because i am working on the new class with new features that isnt yet finished or documented to be uploaded. i acidentally called the other class :3 fixi! Thanks!
    (3am! :'()

    EDIT by Timtower: merged posts
     
    Last edited by a moderator: Mar 15, 2015
    ChipDev and DJSkepter like this.
  9. Offline

    Funnygatt

    All good! This looks awesome btw. I'll definitely be using it.
     
  10. Offline

    mine-care

  11. Offline

    DJSkepter

  12. Offline

    mine-care

    @DJSkepter Yet another speeling mistake of mine, i always mix those :3 (wool with wolf)
    EDIT: F-word! i mixed them again, i mean wolf.
    EDIT#2: added the removeDisguise method you asked above =D

    @axeldu18 I havent added the 1.8 mobs yet but it is only a matter of changinh the enum :p

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: Jun 13, 2016
    ChipDev and DJSkepter like this.
  13. Offline

    ProStriker123

  14. Offline

    mine-care

    @ProStriker123 is the class in the same package?
    A solution would be taking the enum part of the class to a separate enum file. :- )
     
  15. Offline

    ChipDev

    Amazing! Its so nice to see someone is awesome still posts :)
     
    mine-care likes this.
  16. Offline

    nverdier

    I don't understand that grammar... What were you trying to say?
     
  17. Offline

    ChipDev

    Oops! Autocorrect!
    Amazing! Its so nice to see someone that is awesome that still posts!
     
    GrandmaJam and mine-care like this.
  18. Offline

    nverdier

    @ChipDev Are you saying I'm not awesome? :p

    I thought you were leaving the forums lol
     
    teej107 likes this.
  19. Offline

    ChipDev

    Waitwut! Noo!
    I bet you are getting mixed up between threads :3
     
    mine-care likes this.
  20. Offline

    nverdier

  21. Offline

    mine-care

    @ChipDev firstly thanks for your feedback =D really apriciated and secondly, I hate autocorrect too >:-( made be write javadog instead of javadoc xD
     
    ChipDev likes this.
  22. Offline

    ChipDev

    Thats what I should name my dog!
    EDIT; frvr alne don't have a dog
     
    Last edited: Mar 20, 2015
  23. Offline

    mine-care

    @ChipDev The java dog! =D i wish i had a dog :( i could have named him JavaDog! xD
     
    ChipDev likes this.
  24. Offline

    bronzzze

    Is there any way to add armour on mobs or custom itemin hand?


    Btw great job
     
  25. Offline

    Funnygatt

    public MyDisguise(Player p, EntityDisguise type, String name,
    ItemStack inhand, ItemStack helmet, ItemStack chestplate,
    ItemStack leggings, ItemStack boots) {

    Right there in the code :)
     
  26. Offline

    bronzzze

    Thanks dude will try it when i come on pc:)
    i didnt even see it my bad
     
  27. Offline

    Funnygatt

    All good :)
     
  28. Offline

    mine-care

    @bronzzze thanks for your comments =D
    Thanks for helping :- )

    Is there anything else you want me to add;
     
  29. Offline

    bronzzze

    All cool just did I do something wrong beacuse this line get underline with yellow?
    [​IMG]
    It might me my fault

    And i get this error in code:
    [​IMG]
     
    Last edited: Mar 24, 2015
  30. Offline

    mine-care

    @bronzzze no worries :) its deprecated, deprecated does not mean it is wrong or it will cause any problems :3
    in this case, the getMethod (and furthermore invokeMethod) with no arguments (null) is deprecated, no reason for worrries =) your code will work fine
     
Thread Status:
Not open for further replies.

Share This Page