Solved [NMS] Custom Entity is like invisible

Discussion in 'Plugin Development' started by dori99xd, Nov 16, 2014.

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

    dori99xd

    Hey.
    I want a custom villager, which is unpushable (by players) and they can't move.
    So i created a class:
    Code:java
    1. package net.dori99xd.***.listener;
    2.  
    3. import java.lang.reflect.Method;
    4.  
    5. import net.minecraft.server.v1_7_R4.EntityVillager;
    6. import net.minecraft.server.v1_7_R4.World;
    7.  
    8. import org.bukkit.Bukkit;
    9. import org.bukkit.Location;
    10. import org.bukkit.craftbukkit.v1_7_R4.CraftWorld;
    11. import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason;
    12.  
    13. public class CustomEntityVillager extends EntityVillager {
    14.  
    15. public CustomEntityVillager(World world) {
    16. super(world);
    17. }
    18.  
    19. // Removed for testing..
    20. /*
    21. @Override
    22. public void h() {
    23. Bukkit.broadcastMessage("h");
    24. super.h();
    25. }
    26.  
    27. @Override
    28. public void move(double a, double b, double c) {
    29. Bukkit.broadcastMessage("mv");
    30. super.move(a, b, c);
    31. }
    32.  
    33. @Override
    34. public void collide(Entity e) {
    35. Bukkit.broadcastMessage("collide");
    36. super.collide(e);
    37. }
    38. */
    39.  
    40. public static void spawn(Location loc) {
    41. try {
    42. CustomEntityVillager v = new CustomEntityVillager(((CraftWorld) loc.getWorld()).getHandle());
    43. //v.setPosition(location.getX(), location.getY(), location.getZ());
    44. v.setLocation(loc.getX(), loc.getY(), loc.getZ(), 0, 0);
    45. ((CraftWorld)loc.getWorld()).getHandle().addEntity(v);
    46. v.setInvisible(false);
    47. // Don't care if setPostion or setLocation, also tried after spawning
    48. System.out.println("spawned");
    49. } catch (Exception e) {
    50. System.err.println(e.getMessage());
    51. }
    52. }
    53.  
    54. public static void spawnPatched(Location loc) {
    55. try {
    56. if(!patched)
    57. patch();
    58. CustomEntityVillager v2 = new CustomEntityVillager(((CraftWorld) loc.getWorld()).getHandle());
    59. //v.setPosition(location.getX(), location.getY(), location.getZ());
    60. v2.setLocation(loc.getX(), loc.getY(), loc.getZ(), 0, 0);
    61. ((CraftWorld) loc.getWorld()).getHandle().addEntity(v2);
    62. v2.setInvisible(false);
    63. // Don't care if setPostion or setLocation, also tried after spawning
    64. System.out.println("spawned");
    65. } catch (Exception e) {
    66. System.err.println(e.getMessage());
    67. }
    68. }
    69.  
    70. public static boolean patched = false;
    71. public static void patch() {
    72. try {
    73. Method a = net.minecraft.server.v1_7_R4.EntityTypes.class.getDeclaredMethod("a", Class.class, String.class, int.class);
    74. a.setAccessible(true);
    75. a.invoke(a, CustomEntityVillager.class, "CustomVill", 12);
    76. patched = true;
    77. System.out.println("registered");
    78. } catch (Exception e) {
    79. System.err.println(e.getMessage());
    80. patched = false;
    81. }
    82. }
    83. }
    84.  


    Problem is, the villagers are "invisible". I know that they are spawned. The make sounds, but if i activate the hitboxes (F3+B) i dont see they. Why?

    Before i forgot it: Using lastest Patched Spigot Build #1649 with Protocol Hack and CraftBukkit 1.7.10-R0.1.

    Don't care if i use setPostion or setLocation. "spawn" also works without "register" entity (patch method).

    ~dori99xd
     
  2. Offline

    dori99xd

  3. Offline

    dori99xd

    Nobody that can help me?
     
  4. Offline

    DuskFireHD

    Do you want some of my code?. I don't really know the way you do it but I have a nice way using nms :D
     
  5. Offline

    dori99xd

  6. Offline

    DuskFireHD

    dori99xd 1 question how to you like paste like bits of code here?

    Im writing up a small example for you now :D

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

    Funergy

    dori99xd Have you registered the mob?
    This is what I have
    SORRY FOR SPOONFEED
    Code:
    package com.funergy.ss.CustomEntity;
     
    import net.minecraft.server.v1_7_R4.EntityVillager;
    import net.minecraft.server.v1_7_R4.World;
     
    import org.bukkit.Location;
    import org.bukkit.craftbukkit.v1_7_R4.CraftWorld;
    import org.bukkit.craftbukkit.v1_7_R4.entity.CraftLivingEntity;
    import org.bukkit.craftbukkit.v1_7_R4.entity.CraftVillager;
    import org.bukkit.entity.Villager;
    import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason;
    import org.bukkit.util.Vector;
     
    /**
    * @author Funergy
    *
    */
    public class FrozenVillager extends EntityVillager{
       
        public FrozenVillager(World world) {
            super(world);
        }
       
        @Override
        public String t(){
            return "";
        }
     
       
        @Override
        public void move(double d0, double d1, double d2) {
            return;
        }
     
        @Override
        public void g(double x, double y, double z) {
            Vector vector = this.getBukkitEntity().getVelocity();
            super.g(vector.getX(), vector.getY(), vector.getZ());
        }
     
        public static Villager spawn(Location location) {
            World mcWorld = (World) ((CraftWorld) location.getWorld()).getHandle();
            final FrozenVillager customEntity = new FrozenVillager(
                    mcWorld);
            customEntity.setLocation(location.getX(), location.getY(),
                    location.getZ(), location.getYaw(), location.getPitch());
            ((CraftLivingEntity) customEntity.getBukkitEntity())
                    .setRemoveWhenFarAway(false);
            mcWorld.addEntity(customEntity, SpawnReason.CUSTOM);
            return (CraftVillager) customEntity.getBukkitEntity();
        }
     
    }
    
    And this is to register the entity
    Code:
    public class NMSUtils {
        public void registerEntity(String name, int id, Class<? extends EntityInsentient> nmsClass, Class<? extends EntityInsentient> customClass) {
            try {
     
                /*
                * First, we make a list of all HashMap's in the EntityTypes class
                * by looping through all fields. I am using reflection here so we
                * have no problems later when minecraft changes the field's name.
                * By creating a list of these maps we can easily modify them later
                * on.
                */
                List<Map<?, ?>> dataMaps = new ArrayList<Map<?, ?>>();
                for (Field f : EntityTypes.class.getDeclaredFields()) {
                    if (f.getType().getSimpleName().equals(Map.class.getSimpleName())) {
                        f.setAccessible(true);
                        dataMaps.add((Map<?, ?>) f.get(null));
                    }
                }
     
                /*
                * since minecraft checks if an id has already been registered, we
                * have to remove the old entity class before we can register our
                * custom one
                *
                * map 0 is the map with names and map 2 is the map with ids
                */
                if (dataMaps.get(2).containsKey(id)) {
                    dataMaps.get(0).remove(name);
                    dataMaps.get(2).remove(id);
                }
     
                /*
                * now we call the method which adds the entity to the lists in the
                * EntityTypes class, now we are actually 'registering' our entity
                */
                Method method = EntityTypes.class.getDeclaredMethod("a", Class.class, String.class, int.class);
                method.setAccessible(true);
                method.invoke(null, customClass, name, id);
     
                /*
                * after doing the basic registering stuff , we have to register our
                * mob as to be the default for every biome. This can be done by
                * looping through all BiomeBase fields in the BiomeBase class, so
                * we can loop though all available biomes afterwards. Here, again,
                * I am using reflection so we have no problems later when minecraft
                * changes the fields name
                */
                for (Field f : BiomeBase.class.getDeclaredFields()) {
                    if (f.getType().getSimpleName().equals(BiomeBase.class.getSimpleName())) {
                        if (f.get(null) != null) {
     
                            /*
                            * this peace of code is being called for every biome,
                            * we are going to loop through all fields in the
                            * BiomeBase class so we can detect which of them are
                            * Lists (again, to prevent problems when the field's
                            * name changes), by doing this we can easily get the 4
                            * required lists without using the name (which probably
                            * changes every version)
                            */
                            for (Field list : BiomeBase.class.getDeclaredFields()) {
                                if (list.getType().getSimpleName().equals(List.class.getSimpleName())) {
                                    list.setAccessible(true);
                                    @SuppressWarnings("unchecked")
                                    List<BiomeMeta> metaList = (List<BiomeMeta>) list.get(f.get(null));
     
                                    /*
                                    * now we are almost done. This peace of code
                                    * we're in now is called for every biome. Loop
                                    * though the list with BiomeMeta, if the
                                    * BiomeMeta's entity is the one you want to
                                    * change (for example if EntitySkeleton matches
                                    * EntitySkeleton) we will change it to our
                                    * custom entity class
                                    */
                                    for (BiomeMeta meta : metaList) {
                                        Field clazz = BiomeMeta.class.getDeclaredFields()[0];
                                        if (clazz.get(meta).equals(nmsClass)) {
                                            clazz.set(meta, customClass);
                                        }
                                    }
                                }
                            }
     
                        }
                    }
                }
     
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    
    And put this in the onEnable
    Code:
    NMSUtils nms = new NMSUtils();
            nms.registerEntity("Villager", 120, EntityVillager.class, FrozenVillager.class);
     
    dori99xd likes this.
  8. Offline

    dori99xd


    OMG!!! Thanks dude! I think i registered wrong... Thanks!!!
     
  9. Offline

    DuskFireHD

    That's it :D
     
Thread Status:
Not open for further replies.

Share This Page