Development Assistance Custom entity

Discussion in 'Plugin Help/Development/Requests' started by VortexGmer, Apr 5, 2015.

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

    VortexGmer

    Hi, I have a custom entity human, All I want it to do is walk around randomly and look at players when they get close,
    I have no Idea where to start.
    I got this code:
    Code:
    public static void spawnNPC(Player player, Location loc) {
            MinecraftServer nmsServer = ((CraftServer) Bukkit.getServer())
                    .getServer();
            WorldServer nmsWorld = ((CraftWorld) Bukkit.getWorlds().get(0))
                    .getHandle();
            EntityPlayer npc = new EntityPlayer(nmsServer, nmsWorld,
                    new GameProfile(UUID.randomUUID(), "Guard"),
                    new PlayerInteractManager(nmsWorld));
            npc.setLocation(loc.getX(), loc.getY(), loc.getZ(), 45.0F, 0F);
            PlayerConnection connection = ((CraftPlayer) player)
                    .getHandle().playerConnection;
            connection.sendPacket(new PacketPlayOutPlayerInfo(
                    EnumPlayerInfoAction.ADD_PLAYER, npc));
            connection.sendPacket(new PacketPlayOutNamedEntitySpawn(npc));
        }
    but I don't know If I should use this way because I don't really know how to use it, Any help here?
     
    Orange Tabby likes this.
  2. Offline

    Bram0101

    You would probably want to create a custom nms entity with a custom class extended with EntityPlayer. Then you can go into the source of bukkit into the nms entities and search for how they have done some of the things that you want, implement them. You can find info about custom nms entity classes all over the internet (you might need to search a couple of times using different words, or look at projects that are open source and have those classes in them). There are also tutorials about custom entities, you can find with a quick search. For the entity look you can go through every player look at the distant between the entity and player and with calculating a yaw and pitch from a vector (you get the vector with the player location minus the entity location, or in reverse). All of these things can be found with a few searches. So go a head and search it all.
     
  3. Offline

    mine-care

    You can disguse an already spawned entity like a zombie to a human and then it will act as a zombie but it will look like a human :- )
     
  4. Offline

    VortexGmer

    How do you extend entityPlayer and where is the nms source entities stuff
     
  5. Offline

    Bram0101

    There are a lot of tutorials that you can find with a quick search, for example "bukkit custom nms entity". You can also look at people who already made something similar like what you want, and look at their source.
     
  6. Offline

    VortexGmer

    I mean where can I find the 1.8 EntityPlayer code and what about ENtityHuman?
     
  7. Offline

    Bram0101

    You can use a java decompiler to decompile the bukkit jar (It has to be the craftbukkit jar or spigot jar if you are using spigot, because in the bukkit jar itself there are no nms classes). A possible decompiler is jdgui. But decompiling doesn't always give the correct source code, but it's mostly pretty accurate.

    I don't know where the nms source is online. So if anybody knows, feel free to say it.
     
  8. Offline

    VortexGmer

    ok

    @Bram0101
    Ok, How do I clear the flags of the entity and add flags? Right now I can only find a tutorial which replace the vanilla mobs, Not just add more

    <Edit by mrCookieSlime: Merged posts. Please don't double post. There is an Edit Button right next to the Date.>
     
    Last edited by a moderator: Apr 6, 2015
  9. Offline

    Bram0101

    What do you mean? You can replace everything that the entity does. Like methods with overrides, and for fields you could do it in the constructor.
     
  10. Offline

    VortexGmer

    How can I add goals for walking?
     
  11. Offline

    Bram0101

    You can look at how it's done in other classes, like for villagers.
     
  12. Offline

    VortexGmer

    But I don't really understand, I can't do this.goalselector or things because it isn't resolved!!!

    @Bram0101
    It says I need a ((Navigation)getNavigation()).a(true); but I don't have that!

    <Edit by mrCookieSlime: Merged posts. Please don't double post. There is an Edit Button right next to the Date.>
     
  13. Offline

    Bram0101

    I will look at it tomorrow, because it's 23:00 and I'm now on my mobile. And I can't look at it tomorrow until 15:00
     
  14. Offline

    VortexGmer

    ok

    @Bram0101
    I decided to start easier with an entity zombie, It all works except for the part when it is supposed to spawn, It gets called all fine i debugged but the entity doesnt appear,
    Here is my npc code:
    Code:
    package me.VortexGamer.vortexhub.entities;
    
    import java.lang.reflect.Field;
    import java.util.List;
    import java.util.Map;
    
    import net.minecraft.server.v1_8_R1.Entity;
    import net.minecraft.server.v1_8_R1.EntityHuman;
    import net.minecraft.server.v1_8_R1.EntityZombie;
    import net.minecraft.server.v1_8_R1.PathfinderGoalLookAtPlayer;
    import net.minecraft.server.v1_8_R1.PathfinderGoalRandomLookaround;
    import net.minecraft.server.v1_8_R1.PathfinderGoalRandomStroll;
    import net.minecraft.server.v1_8_R1.PathfinderGoalSelector;
    
    import org.bukkit.Location;
    import org.bukkit.craftbukkit.v1_8_R1.CraftWorld;
    
    
    public class NPC extends EntityZombie
    {
        public NPC(org.bukkit.World world)
        {
            super(((CraftWorld)world).getHandle());
            List goalB = (List)getPrivateField("b", PathfinderGoalSelector.class, goalSelector); goalB.clear();
            List goalC = (List)getPrivateField("c", PathfinderGoalSelector.class, goalSelector); goalC.clear();
            List targetB = (List)getPrivateField("b", PathfinderGoalSelector.class, targetSelector); targetB.clear();
            List targetC = (List)getPrivateField("c", PathfinderGoalSelector.class, targetSelector); targetC.clear();
    
            this.goalSelector.a(7, new PathfinderGoalRandomStroll(this, 1.0D));
            this.goalSelector.a(8, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 8.0F));
            this.goalSelector.a(8, new PathfinderGoalRandomLookaround(this));
        }
        public static Object getPrivateField(String fieldName, Class clazz, Object object)
        {
            Field field;
            Object o = null;
            try
            {
                field = clazz.getDeclaredField(fieldName);
                field.setAccessible(true);
                o = field.get(object);
            }
            catch(NoSuchFieldException e)
            {
                e.printStackTrace();
            }
            catch(IllegalAccessException e)
            {
                e.printStackTrace();
            }
            return o;
        }
        public enum EntityTypes
        {
            NPC("NPC", 54, NPC.class);
    
            private EntityTypes(String name, int id, Class<? extends Entity> custom)
            {
                addToMaps(custom, name, id);
            }
    
          public static void spawnEntity(Entity entity, Location loc)
           {
             entity.setLocation(loc.getX(), loc.getY() + 2.5, loc.getZ(), loc.getYaw(),loc.getPitch());
             entity.setInvisible(false);
             ((CraftWorld)loc.getWorld()).getHandle().addEntity(entity);
           }
    
            private static void addToMaps(Class clazz, String name, int id)
            {
                ((Map)getPrivateField("d", net.minecraft.server.v1_8_R1.EntityTypes.class, null)).put(clazz, name);
                ((Map)getPrivateField("f", net.minecraft.server.v1_8_R1.EntityTypes.class, null)).put(clazz, Integer.valueOf(id));
            }
        }
    
    }
    
     
    Last edited by a moderator: Apr 6, 2015
  15. Offline

    VortexGmer

  16. Offline

    Bram0101

    Sorry I totally forget, I was busy with school. I'm going to give you the code that I use to spawn them, and I know I shouldn't because you wouldn't learn much from it, but it's hard for me to explain everything. And I haven't changed your code, so go through it I have said what you should change and find those things and change it, that way I'm not totally spoon fooding you.

    This is for the entity registration, you should call this in the onEnable method (or put it in your onEnable method). I used a class called Dragon so when going through the code just replace those things and the strings with the name of the dragon.
    Code:
    try {
                Class<EntityTypes> entityTypeClass = EntityTypes.class;
    
                Field c = entityTypeClass.getDeclaredField("c");
                c.setAccessible(true);
                HashMap<String, Class<?>> c_map = (HashMap) c.get(null);
                c_map.put("pvpdragon", Dragon.class);
    
                Field d = entityTypeClass.getDeclaredField("d");
                d.setAccessible(true);
                HashMap<Class<?>, String> d_map = (HashMap) d.get(null);
                d_map.put(Dragon.class, "pvpdragon");
    
                Field e = entityTypeClass.getDeclaredField("e");
                e.setAccessible(true);
                HashMap<Integer, Class<?>> e_map = (HashMap) e.get(null);
                e_map.put(Integer.valueOf(63), Dragon.class);
    
                Field f = entityTypeClass.getDeclaredField("f");
                f.setAccessible(true);
                HashMap<Class<?>, Integer> f_map = (HashMap) f.get(null);
                f_map.put(Dragon.class, Integer.valueOf(63));
    
                Field g = entityTypeClass.getDeclaredField("g");
                g.setAccessible(true);
                HashMap<String, Integer> g_map = (HashMap) g.get(null);
                g_map.put("pvpdragon", Integer.valueOf(63));
    
            } catch (Exception exc) {
                Field d;
                int d_map;
                Method[] e;
                Class[] paramTypes = { Class.class, String.class, Integer.TYPE };
                try {
                    Method method = EntityTypes.class.getDeclaredMethod(
                            "addMapping", paramTypes);
                    method.setAccessible(true);
                } catch (Exception ex) {
                    exc.addSuppressed(ex);
                    try {
                        d_map = (e = EntityTypes.class.getDeclaredMethods()).length;
                        for (int d1 = 0; d1 < d_map; d1++) {
                            Method method = e[d1];
                            if (Arrays.equals(paramTypes,
                                    method.getParameterTypes())) {
                                method.invoke(null, new Object[] { Dragon.class,
                                        "pvpdragon", Integer.valueOf(63) });
                            }
                        }
                    } catch (Exception exe) {
                        exc.addSuppressed(exe);
                    }
                    exc.printStackTrace();
                }
            }
    And this is the code to spawn them, it's a bit different than your method like the spawn reason is best to have it to custom, and the same with above I use the dragon class, so just change that and maybe add the setPosition.
    Code:
    net.minecraft.server.v1_8_R2.World w = ((CraftWorld) p.getWorld())
                    .getHandle();
            Dragon dragon = new Dragon(w, p.getLocation(), p);
            w.addEntity(dragon, SpawnReason.CUSTOM);
     
  17. Offline

    VortexGmer

    I don't get what to put in the place where you put Field a,b,c,d,e,f... What do I do??
    Just replace dragon with NPC.class????
    And why
    Integer.valueof(63)??
    and instead of "pvpdragon" i would do "MyZombie"?
     
  18. Offline

    Bram0101

    You only needed to change dragon.class to NPC.class and "pvpdragon" to "MyZombie"and the 63 is the ender dragon entity id. You could replace it with an entity id that's not used
     
  19. Offline

    VortexGmer

    so 52 for zombie right?
     
  20. Offline

    Bram0101

    That's spider, zombie is 54. You can also try 69, because that is an entity id that's not in use. Also I just found something for when the entity register doesn't work, you can also just use what was in the catch block, but the method addMapping should be a. So:
    Code:
    Field d;
                int d_map;
                Method[] e;
                Class[] paramTypes = { Class.class, String.class, Integer.TYPE };
                try {
                    Method method = EntityTypes.class.getDeclaredMethod(
                            "a", paramTypes);
                    method.setAccessible(true);
    method.invoke(null, new Object[] { Dragon.class,
                                        "pvpdragon", Integer.valueOf(63) });
                } catch (Exception ex) {
                    exc.addSuppressed(ex);
                    try {
                        d_map = (e = EntityTypes.class.getDeclaredMethods()).length;
                        for (int d1 = 0; d1 < d_map; d1++) {
                            Method method = e[d1];
                            if (Arrays.equals(paramTypes,
                                    method.getParameterTypes())) {
                                method.invoke(null, new Object[] { Dragon.class,
                                        "pvpdragon", Integer.valueOf(63) });
                            }
                        }
                    } catch (Exception exe) {
                        exc.addSuppressed(exe);
                    }
                    exc.printStackTrace();
                }
     
  21. Offline

    VortexGmer

    I'm getting weird errors here:
    Code:
            NPC npc = new NPC(w, player.getLocation(), player);
    It said that

    Error time!
    Error is The constructor NPC(World, Location, Player) is undefined
    Here is the line:
    Code:
            NPC npc = new NPC(w, player.getLocation(), player);
    Any fix?
     
    Last edited by a moderator: Apr 8, 2015
  22. Offline

    eyamaz

    @VortexGmer Please use the edit button instead of spamming posts please
     
  23. Offline

    Bram0101

    new NPC(w,player.getLocation(),player); is the custom constructor for my dragon class. You need to change it to your constructor.
     
  24. Offline

    VortexGmer

    My constructer is org.Bukkit.World what do I do?
     
  25. Offline

    Bram0101

    You need to use the bukkit world, you would have known this with basic java understanding and some basic bukkit understanding of the player class.

    Also why is this posted in the bukkit alternatives, while this is all in the craftbukkit jar witch is part of the bukkit.
     
  26. Offline

    VortexGmer

    Yes but I cannot use craftworld with org.bukkit.World?
     
  27. Offline

    Bram0101

    Yes you can, because CraftWorld extends World. I changed the world in my code to the nms world instead of any bukkit ones. If you would have looked you would have say that.
     
  28. Offline

    nverdier

     
Thread Status:
Not open for further replies.

Share This Page