NMS How to override default Minecraft mobs

Discussion in 'Resources' started by TeeePeee, Jan 6, 2014.

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

    RingOfStorms

    If that is the same code as the OP, then your code is horribly out dated. You have to go through and update all of your code, especially the NMS portions. All of the reflection in the coded with method names like "az" "a" "b" and what not have probably changed, and you need to look them up and put the new names in.
     
  2. Offline

    GrandpaMizery

    Actually I did that and it looks as if the OP has been updated. Even if it wasn't, that would not explain the error I am getting. But thank you.
     
  3. Offline

    RingOfStorms

    It would explain the error you are getting. It is a cast exception which is pretty much reflection because you have the wrong field name. You are getting a field with some name and that field is a list, not a BiomeDecorator.
     
  4. Offline

    ChipDev

    Look at @Funergy s post.
     
  5. Offline

    GrandpaMizery

    Ok the problem is that I don't have the correct source code for NMS. Does anyone know where to find it.
    Excuse my ignorance, but which post?
     
  6. Offline

    ChipDev

    Sorry, didn't include that :p
    1.8 doesn't require the biomes..
    http://bukkit.org/threads/1-8-only-wasd-entity-control.342899/
    ^ Get the class from there!
     
  7. Offline

    GrandpaMizery

    ok I got things working. I can spawn in a baby cow and it does nothing as expected. I removed all goals.
    This is the method I used to register the custom entity.
    Code:
    @SuppressWarnings("unchecked")
        public static void registerEntity(String name, int id, 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));
                    }
                }
                ((Map<Class<? extends EntityInsentient>, String>) dataMaps.get(1)).put(customClass, name);
                ((Map<Class<? extends EntityInsentient>, Integer>) dataMaps.get(3)).put(customClass, id);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    Now to despawn them when there associated owner leaves the server or when the plugin is unloaded.
     
  8. Offline

    spiroulis

    Awesome Tutorial Thank you so much :)
     
    Last edited: Mar 2, 2015
  9. Offline

    StaticJava

    How do we register our custom entities only in specific worlds?
     
  10. Offline

    Joiner

    Last edited: Mar 4, 2015
  11. Offline

    RingOfStorms

  12. Offline

    Joiner

    @RingOfStorms So what should I do basically?
    Why do I need to use reflection? Why is my client crashing?
    What is wrong with my code exactly?
     
  13. Offline

    RingOfStorms

    You can't just add a custom entity to the world, that is what the OP explains. The method i linked is how I personally do it, you do the reflection to put your class into the hashmaps, then spawn your entity, then put the old one back in.
     
  14. Offline

    Joiner

  15. Offline

    RingOfStorms

    Read the method I gisted and google how to spawn custom mobs in bukkit. There are several posts that go in more explanation . You should be able to figure it out by reading the method and or looking at posts that explain the serveral different ways to do it. Or, since I pretty much spoonfed you could just copy paste my code and write in the reflection yourself and be happy.
     
  16. Offline

    Joiner

    If I could find something, I would not have asked you.
    So bad.
     
  17. Offline

    RingOfStorms

    It's not that bad, you're just asking me to spoon feed you more so idk why you are responding like that. I'm trying to encourage you to read the code I posted and understand it yourself.
     
  18. Offline

    Mammothskier

    @TeeePeee Hello, With the 1.8 Update, mojang has completely removed Giant Zombie's AI. I am working on a plugin that depended on the AI. I mainly need the Giant Zombies to once again target players, however it would also be cool if I could get the Giant Zombies to function a bit more like their smaller counterparts. I would also like to try to get them to be able to target villagers, walk (before they would stay stationary and just look at the target), and of course restore the stomp that would 1 hit a player.

    I have tried to follow this guide and haven't had any luck in restoring any features. No exceptions thrown, just nothing is changing to the Giant's behavior.

    Code:java
    1.  
    2. package me.Mammothskier.Giants.entity;
    3.  
    4. import java.lang.reflect.Field;
    5. import java.util.List;
    6. import java.util.Map;
    7.  
    8. import net.minecraft.server.v1_8_R2.BiomeBase;
    9. import net.minecraft.server.v1_8_R2.BiomeBase.BiomeMeta;
    10. import net.minecraft.server.v1_8_R2.EntityInsentient;
    11. import net.minecraft.server.v1_8_R2.EntityTypes;
    12. import net.minecraft.server.v1_8_R2.EntityGiantZombie;
    13. import org.bukkit.entity.EntityType;
    14.  
    15. public enum CustomEntityType {
    16. GIANT("Giant", 53, EntityType.GIANT, EntityGiantZombie.class, CustomEntityGiantZombie.class);
    17.  
    18. private String name;
    19. private int id;
    20. private EntityType entityType;
    21. private Class<? extends EntityInsentient> nmsClass;
    22. private Class<? extends EntityInsentient> customClass;
    23.  
    24. private CustomEntityType(String name, int id, EntityType entityType, Class<? extends EntityInsentient> nmsClass,
    25. Class<? extends EntityInsentient> customClass) {
    26. this.name = name;
    27. this.id = id;
    28. this.entityType = entityType;
    29. this.nmsClass = nmsClass;
    30. this.customClass = customClass;
    31. }
    32.  
    33. public String getName() {
    34. return name;
    35. }
    36.  
    37. public int getID() {
    38. return id;
    39. }
    40.  
    41. public EntityType getEntityType() {
    42. return entityType;
    43. }
    44.  
    45. public Class<? extends EntityInsentient> getNMSClass() {
    46. return nmsClass;
    47. }
    48.  
    49. public Class<? extends EntityInsentient> getCustomClass() {
    50. return customClass;
    51. }
    52.  
    53. /**
    54.   * Register our entities.
    55.   */
    56. public static void registerEntities() {
    57. for (CustomEntityType entity : values())
    58. a(entity.getCustomClass(), entity.getName(), entity.getID());
    59.  
    60. // BiomeBase#biomes became private.
    61. BiomeBase[] biomes;
    62. try {
    63. biomes = (BiomeBase[]) getPrivateStatic(BiomeBase.class, "biomes");
    64. } catch (Exception exc) {
    65. // Unable to fetch.
    66. return;
    67. }
    68. for (BiomeBase biomeBase : biomes) {
    69. if (biomeBase == null)
    70. break;
    71.  
    72. // This changed names from J, K, L and M.
    73. for (String field : new String[] { "at", "au", "av", "aw" })
    74. try {
    75. Field list = BiomeBase.class.getDeclaredField(field);
    76. list.setAccessible(true);
    77. @SuppressWarnings("unchecked")
    78. List<BiomeMeta> mobList = (List<BiomeMeta>) list.get(biomeBase);
    79.  
    80. // Write in our custom class.
    81. for (BiomeMeta meta : mobList)
    82. for (CustomEntityType entity : values())
    83. if (entity.getNMSClass().equals(meta.b))
    84. meta.b = entity.getCustomClass();
    85. } catch (Exception e) {
    86. e.printStackTrace();
    87. }
    88. }
    89. }
    90.  
    91. /**
    92.   * Unregister our entities to prevent memory leaks. Call on disable.
    93.   */
    94. public static void unregisterEntities() {
    95. for (CustomEntityType entity : values()) {
    96. // Remove our class references.
    97. try {
    98. ((Map) getPrivateStatic(EntityTypes.class, "d")).remove(entity.getCustomClass());
    99. } catch (Exception e) {
    100. e.printStackTrace();
    101. }
    102.  
    103. try {
    104. ((Map) getPrivateStatic(EntityTypes.class, "f")).remove(entity.getCustomClass());
    105. } catch (Exception e) {
    106. e.printStackTrace();
    107. }
    108. }
    109.  
    110. for (CustomEntityType entity : values())
    111. try {
    112. // Unregister each entity by writing the NMS back in place of the custom class.
    113. a(entity.getNMSClass(), entity.getName(), entity.getID());
    114. } catch (Exception e) {
    115. e.printStackTrace();
    116. }
    117.  
    118. // Biomes#biomes was made private so use reflection to get it.
    119. BiomeBase[] biomes;
    120. try {
    121. biomes = (BiomeBase[]) getPrivateStatic(BiomeBase.class, "biomes");
    122. } catch (Exception exc) {
    123. // Unable to fetch.
    124. return;
    125. }
    126. for (BiomeBase biomeBase : biomes) {
    127. if (biomeBase == null)
    128. break;
    129.  
    130. // The list fields changed names but update the meta regardless.
    131. for (String field : new String[] { "as", "at", "au", "av" })
    132. try {
    133. Field list = BiomeBase.class.getDeclaredField(field);
    134. list.setAccessible(true);
    135. @SuppressWarnings("unchecked")
    136. List<BiomeMeta> mobList = (List<BiomeMeta>) list.get(biomeBase);
    137.  
    138. // Make sure the NMS class is written back over our custom class.
    139. for (BiomeMeta meta : mobList)
    140. for (CustomEntityType entity : values())
    141. if (entity.getCustomClass().equals(meta.b))
    142. meta.b = entity.getNMSClass();
    143. } catch (Exception e) {
    144. e.printStackTrace();
    145. }
    146. }
    147. }
    148.  
    149. /**
    150.   * A convenience method.
    151.   * @param clazz The class.
    152.   * @param f The string representation of the private static field.
    153.   * @return The object found
    154.   * @throws Exception if unable to get the object.
    155.   */
    156. private static Object getPrivateStatic(Class clazz, String f) throws Exception {
    157. Field field = clazz.getDeclaredField(f);
    158. field.setAccessible(true);
    159. return field.get(null);
    160. }
    161.  
    162. /*
    163.   * Since 1.7.2 added a check in their entity registration, simply bypass it and write to the maps ourself.
    164.   */
    165. private static void a(Class paramClass, String paramString, int paramInt) {
    166. try {
    167. ((Map) getPrivateStatic(EntityTypes.class, "c")).put(paramString, paramClass);
    168. ((Map) getPrivateStatic(EntityTypes.class, "d")).put(paramClass, paramString);
    169. ((Map) getPrivateStatic(EntityTypes.class, "e")).put(Integer.valueOf(paramInt), paramClass);
    170. ((Map) getPrivateStatic(EntityTypes.class, "f")).put(paramClass, Integer.valueOf(paramInt));
    171. ((Map) getPrivateStatic(EntityTypes.class, "g")).put(paramString, Integer.valueOf(paramInt));
    172. } catch (Exception exc) {
    173. // Unable to register the new class.
    174. }
    175. }
    176. }
    177.  

    and my CustomEntityGiantZombie class
    Code:java
    1.  
    2. package me.Mammothskier.Giants.entity;
    3.  
    4. import java.lang.reflect.Field;
    5. import java.util.List;
    6.  
    7. import net.minecraft.server.v1_8_R2.EntityGiantZombie;
    8. import net.minecraft.server.v1_8_R2.EntityHuman;
    9. import net.minecraft.server.v1_8_R2.EntityVillager;
    10. import net.minecraft.server.v1_8_R2.PathfinderGoalFloat;
    11. import net.minecraft.server.v1_8_R2.PathfinderGoalHurtByTarget;
    12. import net.minecraft.server.v1_8_R2.PathfinderGoalLookAtPlayer;
    13. import net.minecraft.server.v1_8_R2.PathfinderGoalMeleeAttack;
    14. import net.minecraft.server.v1_8_R2.PathfinderGoalMoveThroughVillage;
    15. import net.minecraft.server.v1_8_R2.PathfinderGoalMoveTowardsRestriction;
    16. import net.minecraft.server.v1_8_R2.PathfinderGoalNearestAttackableTarget;
    17. import net.minecraft.server.v1_8_R2.PathfinderGoalRandomLookaround;
    18. import net.minecraft.server.v1_8_R2.PathfinderGoalRandomStroll;
    19. import net.minecraft.server.v1_8_R2.PathfinderGoalSelector;
    20. import net.minecraft.server.v1_8_R2.World;
    21.  
    22. public class CustomEntityGiantZombie extends EntityGiantZombie {
    23.  
    24. public CustomEntityGiantZombie(World world) {
    25. super(world);
    26.  
    27. List<?> goalB = (List<?>)getPrivateField("b", PathfinderGoalSelector.class, goalSelector); goalB.clear();
    28. List<?> goalC = (List<?>)getPrivateField("c", PathfinderGoalSelector.class, goalSelector); goalC.clear();
    29. List<?> targetB = (List<?>)getPrivateField("b", PathfinderGoalSelector.class, targetSelector); targetB.clear();
    30. List<?> targetC = (List<?>)getPrivateField("c", PathfinderGoalSelector.class, targetSelector); targetC.clear();
    31.  
    32. this.goalSelector.a(0, new PathfinderGoalFloat(this));
    33. this.goalSelector.a(2, new PathfinderGoalMeleeAttack(this, EntityHuman.class, 1.0D, false));
    34. this.goalSelector.a(4, new PathfinderGoalMeleeAttack(this, EntityVillager.class, 1.0D, true));
    35. this.goalSelector.a(5, new PathfinderGoalMoveTowardsRestriction(this, 1.0D));
    36. this.goalSelector.a(6, new PathfinderGoalMoveThroughVillage(this, 1.0D, false));
    37. this.goalSelector.a(7, new PathfinderGoalRandomStroll(this, 1.0D));
    38. this.goalSelector.a(8, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 8.0F));
    39. this.goalSelector.a(8, new PathfinderGoalRandomLookaround(this));
    40. this.targetSelector.a(1, new PathfinderGoalHurtByTarget(this, true));
    41. this.targetSelector.a(2, new PathfinderGoalNearestAttackableTarget<EntityHuman>(this, EntityHuman.class, true));
    42. this.targetSelector.a(2, new PathfinderGoalNearestAttackableTarget<EntityVillager>(this, EntityVillager.class, false));
    43. }
    44.  
    45. public static Object getPrivateField(String fieldName, Class<PathfinderGoalSelector> clazz, Object object)
    46. {
    47. Field field;
    48. Object o = null;
    49. try
    50. {
    51. field = clazz.getDeclaredField(fieldName);
    52. field.setAccessible(true);
    53. o = field.get(object);
    54. }
    55. {
    56. e.printStackTrace();
    57. }
    58. {
    59. e.printStackTrace();
    60. }
    61. return o;
    62. }
    63. }
     
  19. Offline

    VortexGmer

    How would you do this so instead of overriding the zombie it creates a new type of zombie?
     
  20. Offline

    Scullyking

    Hi, @TeeePeee - couple of questions.

    1. Is this method still relevant and the best way of doing things? I'm only asking because I'm aware of methods of doing things changing drastically in short periods of time with bukkit.
    2. In a project I am working on, I need multiple custom types of multiple mobs. (E.g a weak zombie, a strong zombie, and a boss zombie). How can I do this, and is there a tutorial you recommend?

    Thanks
     
  21. Offline

    RingOfStorms

    well this is the tutorial and the process of overriding hasn't changed. On the topic of different types of zombies, it will be easiest to build the implementation of all three into one class and just switch which one it uses, or you'll have to inject each class when you spawn in that monster in order for the server to use the correct class each time.
     
  22. Offline

    sokka999

    @TeeePeee With this can I edit an entities model?
     
  23. Offline

    RingOfStorms

    No, this is still only server side implementations of an entity, you must use a resourcepack in order to have custom models. To set up a resource pack do some googling as that gets a bit off topic for this thread.
     
  24. Offline

    BurnerDiamond

    Sorry to bump such an old post but what if I wanted it not to override all the vanilla mobs but spawn it with a command?
     
  25. Offline

    Konato_K

    @BurnerDiamond Then you just make the entity that extends the NMS one and manually spawn it by making a new instance, adding it to the world and setting it's location.
     
  26. After I customized my entity then how do I spawn it? Also is there a way to not make players push my custom entity?
     
  27. Offline

    sachal2406

    How to keep default mobs? Like have my custom mobs that I can spawn but keep default mobs of Minecraft.
     
  28. Offline

    Mammothskier

    This was literally just answered 2 posts above yours.
     
  29. Offline

    MrKravis

  30. Offline

    Europia79

Thread Status:
Not open for further replies.

Share This Page