Registering custom mobs without replacing the default ones.

Discussion in 'Plugin Development' started by IconByte, Aug 18, 2015.

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

    IconByte

    Hello.
    I am having problem where when I register my custom mobs, then default ones are getting the same values/effects what custom mobs have. Sorry, I don't know how to explain it nicely.

    Anyways I used this code to register my custom mobs, but then the other default minecraft mobs are affected also.. But I would like to spawn in these custom mobs by myself whenever I want:
    Code:
        public void registerEntity(String name, int id, Class<? extends EntityInsentient> nmsClass, Class<? extends EntityInsentient> customClass) {
            try {
                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));
                    }
                }
                if (dataMaps.get(2).containsKey(id)) {
                    dataMaps.get(0).remove(name);
                    dataMaps.get(2).remove(id);
                }
    
                Method method = EntityTypes.class.getDeclaredMethod("a", Class.class, String.class, int.class);
                method.setAccessible(true);
                method.invoke(null, customClass, name, id);
    
                for (Field f : BiomeBase.class.getDeclaredFields()) {
                    if (f.getType().getSimpleName().equals(BiomeBase.class.getSimpleName())) {
                        if (f.get(null) != null) {
                            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));
    
                                    for (BiomeMeta meta : metaList) {
                                        Field clazz = BiomeMeta.class.getDeclaredFields()[0];
                                        if (clazz.get(meta).equals(nmsClass)) {
                                            clazz.set(meta, customClass);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            } catch (Exception e) {}
        }
     
  2. Offline

    finalblade1234

    Using reflection, you can access Maps c,d,f and g in EntityTypes, and add your entity/id to them.
    Method to get the fields from EntityTypes (replacing "version" with v1_8R3 or whatever your version is):
    Code:
    protected static Field mapStringToClassField, mapClassToStringField, mapClassToIdField, mapStringToIdField;
        static {
            try {
                mapStringToClassField = net.minecraft.server.version.EntityTypes.class.getDeclaredField("c");
                mapClassToStringField = net.minecraft.server.version.EntityTypes.class.getDeclaredField("d");
                mapClassToIdField = net.minecraft.server.version.EntityTypes.class.getDeclaredField("f");
                mapStringToIdField = net.minecraft.server.version.EntityTypes.class.getDeclaredField("g");
    
                mapStringToClassField.setAccessible(true);
                mapClassToStringField.setAccessible(true);
                mapClassToIdField.setAccessible(true);
                mapStringToIdField.setAccessible(true);
            }
            catch(Exception e) {e.printStackTrace();}
        }
    Now the method to put the values in EntityTypes maps.
    Code:
    public static void addCustomEntity(Class entityClass, String name, int id) {
    if (mapStringToClassField == null || mapStringToIdField == null || mapClassToStringField == null || mapClassToIdField == null) {
    return;} else {
    try {
    Map mapStringToClass = (Map) mapStringToClassField.get(null);Map mapStringToId = (Map) mapStringToIdField.get(null);Map mapClassToString = (Map) mapClassToStringField.get(null);Map mapClassToId = (Map) mapClassToIdField.get(null);mapStringToClass.put(name, entityClass);mapStringToId.put(name, Integer.valueOf(id));mapClassToString.put(entityClass, name);mapClassToId.put(entityClass, Integer.valueOf(id));}
    catch (Exception e) {
    e.printStackTrace();}
    }
    }
    
    And finally, spawning your custom mob:
    Code:
    net.minecraft.server.version.World nmsWorld = ((CraftWorld) loc.getWorld()).getHandle();
    YourCustomClass mob = new YourCustomClass(loc.getWorld(), owner);
    mob.setPosition(x, y, z);
    nmsWorld.addEntity(mob);
    org.bukkit.entity.Entity bukkitEntity = (org.bukkit.entity.Entity) mob.getBukkitEntity(); 
    
    All code+methods courtesy of: https://www.spigotmc.org/threads/tutorial-creating-custom-entities-with-pathfindergoals.18519/
     
    Last edited: Aug 18, 2015
    IconByte likes this.
Thread Status:
Not open for further replies.

Share This Page