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

    AstramG

  2. Offline

    TeeePeee

    TwoPointDuck
    This code will remove all Pathfinders from the Insentient Entity it is executed from.
    Code:java
    1. try {
    2. Field bField = PathfinderGoalSelector.class.getDeclaredField("b");
    3. bField.setAccessible(true);
    4. Field cField = PathfinderGoalSelector.class.getDeclaredField("c");
    5. cField.setAccessible(true);
    6. bField.set(goalSelector, new UnsafeList<PathfinderGoalSelector>());
    7. bField.set(targetSelector, new UnsafeList<PathfinderGoalSelector>());
    8. cField.set(goalSelector, new UnsafeList<PathfinderGoalSelector>());
    9. cField.set(targetSelector, new UnsafeList<PathfinderGoalSelector>());
    10. } catch (Exception exc) {
    11. exc.printStackTrace();
    12. }
     
  3. Offline

    GreySwordz

    TeeePeee For some reason clearing all pathfinders does not work. I am copy pasting exactly that code and adding no new ones, however, it still behaves like a vanilla mob.

    EDIT: Problem is only with giants, acts like vanilla no matter what. code:
    Code:
    public class EntityCustomGiant extends EntityGiant  {
        public EntityCustomGiant (World world) {
            super(world);
     
            System.out.println("constructor call");
            try {
                Field bField = PathfinderGoalSelector.class.getDeclaredField("b");
                bField.setAccessible(true);
                Field cField = PathfinderGoalSelector.class.getDeclaredField("c");
                cField.setAccessible(true);
                bField.set(goalSelector, new UnsafeList<PathfinderGoalSelector>());
                bField.set(targetSelector, new UnsafeList<PathfinderGoalSelector>());
                cField.set(goalSelector, new UnsafeList<PathfinderGoalSelector>());
                cField.set(targetSelector, new UnsafeList<PathfinderGoalSelector>());
            } catch (Exception exc) {
                exc.printStackTrace();
            }
         
            this.goalSelector.a(0, new PathfinderGoalLookAtPlayer(this, EntityPlayer.class, 8.0F));
            this.goalSelector.a(1, new PathfinderGoalTempt(this, 1.0D, Items.BLAZE_ROD, false));
     
        }
    }
    EIDT2: If I register them as Giants but extend EntityZombie, it works. Is there a better way?
     
  4. Offline

    HelGod

    Does anyone know how I can remove the randomstroll from villagers?
     
  5. Offline

    TeeePeee

    GreySwordz
    In my project, I extend EntityGiantZombie and after clearing the Pathfinders, I use this code to re-add new Pathfinders:
    Code:java
    1. getNavigation().b(true);
    2. goalSelector.a(0, new PathfinderGoalFloat(this));
    3. goalSelector.a(2, new PathfinderGoalZombieAttack(this, EntityHuman.class, (Double) Configuration.getConfig("mobs.giant.speed"),
    4. false));
    5. goalSelector.a(3, new PathfinderGoalZombieAttack(this, EntityVillager.class, (Double) Configuration.getConfig("mobs.giant.speed"),
    6. true));
    7. goalSelector.a(4, new PathfinderGoalMoveTowardsRestriction(this, 1.0D));
    8. goalSelector.a(5, new PathfinderGoalMoveThroughVillage(this, 1.0D, false));
    9. goalSelector.a(6, new PathfinderGoalRandomStroll(this, 1.0D));
    10. goalSelector.a(7, new PathfinderGoalLookAtTarget(this, EntityHuman.class, 8.0F));
    11. goalSelector.a(7, new PathfinderGoalRandomLookaround(this));
    12. targetSelector.a(1, new PathfinderGoalHurtByTarget(this, true));
    13. goalSelector.a(1, new PathfinderGoalLeapAtTarget(this, 1.3F));
    14. targetSelector.a(2, new PathfinderGoalNearestAttackableZombieTarget(this, EntityHuman.class, 0, true));
    15. targetSelector.a(2, new PathfinderGoalNearestAttackableZombieTarget(this, EntityVillager.class, 0, false));


    (seen here)

    I'm not sure what my logic was at the time about the call to getNavigation().b(true) but my code seems to work.

    HelGod
    The easiest way is to simply clear all the pathfinders (see code here) and then find the villager pathfinders and re-add them (other than the one you don't want ie. RandomStroll).
     
  6. Offline

    Rascal Two

    Hey all, I can’t seem to update this to 1.7.5 for the life of me. It was working perfectly in 1.7.2, but when I updated it to 1.7.5 it didn’t work. (Yes I changed from aD() to aC(), still nothing)
    Code:java
    1. publicclass RascalsZombie extends EntityZombie{
    2. public RascalsZombie(World world){
    3. super(world);
    4. }
    5. @Override
    6. protected void aC(){
    7. super.aC();
    8. this.getAttributeInstance(GenericAttributes.a).setValue(35.0);
    9. }
    10. }

    Now the code doesn’t give any errors whatsoever – and I put debug codes in the aC(), so I know it is being loaded – but the attribute doesn’t get applied at all. Strangely, when I add a debug code to output the value of the attribute before and after me setting it, it shows before it being default (20.0) and after it outputs as what I set it to (35.0). When trying to add “this.bb().b(GenericAttributes.a);” (Which I never needed in 1.7.2) I get console spamming of errors, with the main one being “[10:51:59 WARN]: Caused by: java.lang.IllegalArgumentException: Attribute is already registered!”. Here’s the Enum in my override class (everything else is the same, so no point in showing): ZOMBIE(“Zombie”, 54, EntityType.ZOMBIE, EntityZombie.class, RascalsZombie.class;

    I usually just trial and error things like this on my own, but this one really has me stumped; it could be something right in front of my nose I’m missing, I got no clue at this point. Hope Someone out there can help!
     
  7. Offline

    GreySwordz

    TeeePeee Still doesn't work. Perhaps the problem lies within the first argument of goalselector.a?
     
  8. Offline

    Europia79

    TeeePeee

    Great tutorial.

    My custom mob extends EntityVillager and implements EntityOwnable. The only functionality that I require is for a Villager to toggle stay+follow a player on right-click. That's why I figure that I would try implement EntityOwnable and then modify the constructor of PathfinderGoalFollowOwner to accept my mob instead of EntityTamableAnimal.

    Unfortunately, it doesn't completely work. Villagers will just stand still, which is very good: that's what I want. But they won't follow on-right-click. Here are all my files:

    Main,Listnener,CustomVillager,PathfinderGoal (open)

    MainPlugin.java (open)

    Code:java
    1. package mc.euro.extraction;
    2.  
    3. import mc.euro.extraction.debug.*;
    4. import mc.euro.extraction.teeepeee.CustomEntityType;
    5. import org.bukkit.plugin.java.JavaPlugin;
    6.  
    7. /**
    8. *
    9. * @author Nikolai
    10. */
    11. public class HostagePlugin extends JavaPlugin {
    12.  
    13. DebugInterface debug;
    14.  
    15. @Override
    16. public void onEnable() {
    17. debug = new DebugOn(this);
    18. getServer().getPluginManager().registerEvents(new HostageArena(), this);
    19. CustomEntityType.registerEntities();
    20. }
    21.  
    22. @Override
    23. public void onDisable() {
    24. super.onDisable();
    25. CustomEntityType.unregisterEntities();
    26. }
    27.  
    28. }
    29.  


    VillagerListener.java (open)

    Code:java
    1. package mc.euro.extraction;
    2.  
    3. import mc.euro.extraction.entity.Hostage;
    4. import java.util.ArrayList;
    5. import java.util.List;
    6. import org.bukkit.Bukkit;
    7. import org.bukkit.craftbukkit.v1_7_R1.entity.CraftEntity;
    8. import org.bukkit.entity.Entity;
    9. import org.bukkit.entity.EntityType;
    10. import org.bukkit.entity.Player;
    11. import org.bukkit.entity.Villager;
    12. import org.bukkit.event.EventHandler;
    13. import org.bukkit.event.EventPriority;
    14. import org.bukkit.event.Listener;
    15. import org.bukkit.event.entity.CreatureSpawnEvent;
    16. import org.bukkit.event.inventory.InventoryOpenEvent;
    17. import org.bukkit.event.inventory.InventoryType;
    18. import org.bukkit.event.player.PlayerInteractEntityEvent;
    19.  
    20. /**
    21. *
    22. * @author Nikolai
    23. */
    24. public class HostageArena implements Listener {
    25.  
    26. HostagePlugin plugin;
    27. List<Hostage> vips;
    28.  
    29. public HostageArena() {
    30. this.plugin = (HostagePlugin) Bukkit.getServer().getPluginManager().getPlugin("HostageArena");
    31. vips = new ArrayList<Hostage>();
    32. }
    33.  
    34. @EventHandler (priority=EventPriority.HIGHEST)
    35. public void onSpawn(CreatureSpawnEvent e) {
    36. if (e.getEntity().getType() != EntityType.VILLAGER) return;
    37.  
    38. Villager v = (Villager) e.getEntity();
    39. v.setCustomName("Hostage");
    40.  
    41. }
    42.  
    43. @EventHandler (priority=EventPriority.HIGHEST)
    44. public void onHostageInteract(PlayerInteractEntityEvent e) {
    45. if (e.getRightClicked().getType() != EntityType.VILLAGER) return;
    46.  
    47. Entity E = e.getRightClicked();
    48. Hostage h = (Hostage) ((CraftEntity)E).getHandle();
    49.  
    50. Player p = (Player) e.getPlayer();
    51.  
    52. if (h.isFollowing()) {
    53. h.stay();
    54. } else if (h.isStopped()) {
    55. h.follow(p.getName());
    56. }
    57. }
    58.  
    59. @EventHandler (priority=EventPriority.HIGHEST)
    60. public void onInvOpen(InventoryOpenEvent e) {
    61. if (e.getInventory().getType() != InventoryType.MERCHANT) return;
    62. e.setCancelled(true);
    63. }
    64.  
    65. }
    66.  


    CustomEntityType.java (open)

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


    CustomVillager.java (open)

    Code:java
    1. package mc.euro.extraction.entity;
    2.  
    3. import java.lang.reflect.Field;
    4. import mc.euro.extraction.pathfinders.PathfinderGoalFollowPlayer;
    5. import net.minecraft.server.v1_7_R1.Entity;
    6. import net.minecraft.server.v1_7_R1.EntityOwnable;
    7. import net.minecraft.server.v1_7_R1.EntityVillager;
    8. import net.minecraft.server.v1_7_R1.PathfinderGoalSelector;
    9. import net.minecraft.server.v1_7_R1.World;
    10. import org.bukkit.Bukkit;
    11. import org.bukkit.craftbukkit.v1_7_R1.util.UnsafeList;
    12. import org.bukkit.entity.Player;
    13.  
    14. /**
    15. *
    16. * @author Nikolai
    17. */
    18. public class Hostage extends EntityVillager implements EntityOwnable {
    19.  
    20. String owner;
    21. int ownerID;
    22. World world2;
    23.  
    24. public Hostage(World w) {
    25. super(w);
    26. this.world2 = w;
    27. clearPathfinders();
    28. this.goalSelector.a(10, new PathfinderGoalFollowPlayer(this, 1.0D, 10.0F, 5.0F));
    29. }
    30.  
    31. public Hostage(World w, int profession) {
    32. super(w, profession);
    33. this.world2 = w;
    34. clearPathfinders();
    35. this.goalSelector.a(10, new PathfinderGoalFollowPlayer(this, 1.0D, 10.0F, 5.0F));
    36. }
    37.  
    38. private void clearPathfinders() {
    39. try {
    40. Field bField = PathfinderGoalSelector.class.getDeclaredField("b");
    41. bField.setAccessible(true);
    42. Field cField = PathfinderGoalSelector.class.getDeclaredField("c");
    43. cField.setAccessible(true);
    44. bField.set(goalSelector, new UnsafeList<PathfinderGoalSelector>());
    45. bField.set(targetSelector, new UnsafeList<PathfinderGoalSelector>());
    46. cField.set(goalSelector, new UnsafeList<PathfinderGoalSelector>());
    47. cField.set(targetSelector, new UnsafeList<PathfinderGoalSelector>());
    48. } catch (Exception exc) {
    49. exc.printStackTrace();
    50. }
    51. }
    52.  
    53. public void stay() {
    54. this.owner = null;
    55. }
    56.  
    57. public boolean isStopped() {
    58. if (this.owner == null) return true;
    59. return false;
    60. }
    61.  
    62. public boolean isFollowing() {
    63. if (this.owner == null) return false;
    64. return true;
    65. }
    66.  
    67. public void follow(Player p) {
    68. this.owner = p.getName();
    69. }
    70.  
    71. public void follow(String p) {
    72. this.owner = p;
    73. }
    74.  
    75. public void setOwner(Player p) {
    76. this.owner = p.getName();
    77. this.ownerID = p.getEntityId();
    78. }
    79.  
    80. public void setOwner(String name) {
    81. this.owner = name;
    82. }
    83.  
    84. @Override
    85. public String getOwnerName() {
    86. return this.owner;
    87. }
    88.  
    89. @Override
    90. public Entity getOwner() {
    91. if (this.owner == null) return null;
    92. Player player = (Player) Bukkit.getPlayer(this.owner);
    93. int id = player.getEntityId();
    94. Entity E = (Entity) this.world.getEntity(id);
    95. return E;
    96. // return this.world.getEntity(this.ownerID);
    97. }
    98.  
    99. }
    100.  


    PathfinderGoalFollowPlayer.java (open)

    Code:java
    1. package mc.euro.extraction.pathfinders;
    2.  
    3. import mc.euro.extraction.entity.Hostage;
    4. import net.minecraft.server.v1_7_R1.EntityLiving;
    5. import net.minecraft.server.v1_7_R1.MathHelper;
    6. import net.minecraft.server.v1_7_R1.Navigation;
    7. import net.minecraft.server.v1_7_R1.PathfinderGoal;
    8. import net.minecraft.server.v1_7_R1.World;
    9.  
    10. /**
    11. * Modified PathfinderGoalFollowOwner <br/><br/>
    12. *
    13. * @author Nikolai
    14. */
    15. public class PathfinderGoalFollowPlayer extends PathfinderGoal {
    16. private Hostage d;
    17. private EntityLiving e;
    18. World a;
    19. private double f;
    20. private Navigation g;
    21. private int h;
    22. float b;
    23. float c;
    24. private boolean i;
    25.  
    26. public PathfinderGoalFollowPlayer(Hostage paramHostage, double paramDouble, float paramFloat1, float paramFloat2)
    27. {
    28. this.d = paramHostage;
    29. this.a = paramHostage.world;
    30. this.f = paramDouble;
    31. this.g = paramHostage.getNavigation();
    32. this.c = paramFloat1;
    33. this.b = paramFloat2;
    34. a(3);
    35. }
    36.  
    37. public boolean a()
    38. {
    39. EntityLiving localEntityLiving = (EntityLiving) this.d.getOwner();
    40. if (localEntityLiving == null) {
    41. return false;
    42. }
    43. if (this.d.e(localEntityLiving) < this.c * this.c) {
    44. return false;
    45. }
    46. this.e = localEntityLiving;
    47. return true;
    48. }
    49.  
    50. @Override
    51. public boolean b()
    52. {
    53. return (!this.g.g()) && (this.d.e(this.e) > this.b * this.b);
    54. }
    55.  
    56. @Override
    57. public void c()
    58. {
    59. this.h = 0;
    60. this.i = this.d.getNavigation().a();
    61. this.d.getNavigation().a(false);
    62. }
    63.  
    64. @Override
    65. public void d()
    66. {
    67. this.e = null;
    68. this.g.h();
    69. this.d.getNavigation().a(this.i);
    70. }
    71.  
    72. @Override
    73. public void e()
    74. {
    75. this.d.getControllerLook().a(this.e, 10.0F, this.d.x());
    76. if (--this.h > 0) {
    77. return;
    78. }
    79. this.h = 10;
    80. if (this.g.a(this.e, this.f)) {
    81. return;
    82. }
    83. if (this.d.bL()) {
    84. return;
    85. }
    86. if (this.d.e(this.e) < 144.0D) {
    87. return;
    88. }
    89. int j = MathHelper.floor(this.e.locX) - 2;
    90. int k = MathHelper.floor(this.e.locZ) - 2;
    91. int m = MathHelper.floor(this.e.boundingBox.b);
    92. for (int n = 0; n <= 4; n++) {
    93. for (int i1 = 0; i1 <= 4; i1++) {
    94. if ((n < 1) || (i1 < 1) || (n > 3) || (i1 > 3)) {
    95. if ((World.a(this.a, j + n, m - 1, k + i1)) && (!this.a.getType(j + n, m, k + i1).r()) && (!this.a.getType(j + n, m + 1, k + i1).r()))
    96. {
    97. this.d.setPositionRotation(j + n + 0.5F, m, k + i1 + 0.5F, this.d.yaw, this.d.pitch);
    98. this.g.h();
    99. return;
    100. }
    101. }
    102. }
    103. }
    104. }
    105. }
    106.  




    Do you have a guess of what might be wrong ? Or possibly another way of implementing this functionality ? (there are no errors). I'm not even completely sure of where I should put my debugging lines since there are no errors. I guess I could first check the value of the owner to see if it's getting changed. Another than that, I'm not sure.

    TeeePeee

    Oh my god, it fucking works beautifully! Thanks!

    I think the major change was that one of the Pathfinder methods had a missing @Override.

    Also, reading thru the obfuscated code, I found out that the last two float parameters for the PathfinderGoalFollowPlayer constructor are used for the distance checks. The method e(Entity) for the class Entity returns a distanceSquared (pretty easy to figure out).

    Oh my god man, thank you so much again for such an awesome tutorial (i read them ALL. This one was the best).

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: Jan 25, 2016
  9. I have a problem where my values dont seem to be set. i am trying to change the follow distance so zombies will target a player at a further distance.
    i have done
    Code:java
    1. public class CustomZombie extends EntityZombie{
    2.  
    3. public CustomZombie(World world){
    4. super(world);
    5. }
    6. @Override
    7. protected void aC(){
    8. super.aC();
    9. this.getAttributeInstance(GenericAttributes.b).setValue(800.0D); //Follow Distance
    10. this.getAttributeInstance(GenericAttributes.d).setValue(5.8D); //Speed Distance
    11. }
    12.  

    but it seems not to take effect. i know i am missing something so any help is appreciated.
    EDIT: i ramped up the speed to see if it does change but it doesnt. and i have also shoved a println in there once to make sure it was running and it was (pages of spam proved that)
     
  10. Offline

    Europia79

    TeeePeee

    I'm encountering a small problem while working on backwards compatibility

    EntityInsentient exists from 1_6_R1 to 1_7_R3

    However, EntityInsentient does not exist prior to 1_6_R1

    So for 1.2.5 to 1.5.2, should I use EntityLiving as a replacement ? I mean, I tried this replacement, and it didn't work, but that doesn't necessarily mean it's the problem. I checked over every piece of obfuscated field to make sure the references are correct, but I might have missed one.

    Also, while reading thru the CustomEntityType code here

    Code:java
    1. // This changed names from J, K, L and M.
    2. for (String field : new String[] { "J", "K", "L", "M" })
    3. try {
    4. Field list = BiomeBase.class.getDeclaredField(field);
    5. list.setAccessible(true);
    6. @SuppressWarnings("unchecked")
    7. List<BiomeMeta> mobList = (List<BiomeMeta>) list.get(biomeBase);
    8.  
    9. // Write in our custom class.
    10. for (BiomeMeta meta : mobList)
    11. for (CustomEntityType entity : values())
    12. if (entity.getNMSClass().equals(meta.b))
    13. meta.b = entity.getCustomClass();
    14. } catch (Exception e) {
    15. e.printStackTrace();


    It lead me to inspect the BiomeBase class:

    These are the entities added for 1.7.2
    Code:java
    1. this.at.add(new BiomeMeta(EntitySheep.class, 12, 4, 4));
    2. this.at.add(new BiomeMeta(EntityPig.class, 10, 4, 4));
    3. this.at.add(new BiomeMeta(EntityChicken.class, 10, 4, 4));
    4. this.at.add(new BiomeMeta(EntityCow.class, 8, 4, 4));
    5.  
    6. this.as.add(new BiomeMeta(EntitySpider.class, 100, 4, 4));
    7. this.as.add(new BiomeMeta(EntityZombie.class, 100, 4, 4));
    8. this.as.add(new BiomeMeta(EntitySkeleton.class, 100, 4, 4));
    9. this.as.add(new BiomeMeta(EntityCreeper.class, 100, 4, 4));
    10. this.as.add(new BiomeMeta(EntitySlime.class, 100, 4, 4));
    11. this.as.add(new BiomeMeta(EntityEnderman.class, 10, 1, 4));
    12. this.as.add(new BiomeMeta(EntityWitch.class, 5, 1, 1));
    13.  
    14.  
    15.  
    16. this.au.add(new BiomeMeta(EntitySquid.class, 10, 4, 4));
    17.  
    18. this.av.add(new BiomeMeta(EntityBat.class, 10, 8, 8));


    1.5.1 is the same except the names of the Lists are J, K, L, M. And it doesn't register EntityWitch.

    So if i'm reading your code correctly, you only want to overwrite BiomeMeta that already exists ? For all those hostiles mobs, is that the night-time biome ? For the squid, is that the water biome ?

    Sorry, just talking out loud... Trying to figure out where the problem is. Looks like my EntityVillager never gets written to one of those lists... but that shouldn't be a problem because it's tested and working for 1.6.1 to 1.7.9

    Just not working on 1.5.2 or 1.5.1 ...I'll go back over every bit of code to see if i can find the mistake. Just thought I would ask in case you're already familiar with stuff for 1.2.5 to 1.5.2

    The problem may very well be the lack of EntityInsentient and that it needs to be replaced with something other than EntityLiving.

    (Btw, same exact code in my previous post except changed NMS fields names to 1.5.1 & 1.5.2)

    EDIT: Btw, the problem for 1.5.2 and 1.5.1 is that the mobs are appearing and disappearing (no errors). Tested with spawn egg Villager and Spawner for a Villager. Same Result.
     
  11. Offline

    RSXLV

    I've applied this method to 1.7.9 R0.2 (v1_7_R3 NMS). However, the zombies are not updated in all biomes, i.e. Extreme Hills, whilst they work in (regular?) Forest and presumably others.

    Additionally, may I request that you change aD() to aC() for 1_7_R3 accuracy?
     
  12. Offline

    TwoPointDuck

    Is there a way to turn down the range for the seeking pathfinders:
    Code:
    this.goalSelector.a(2, new PathfinderGoalMeleeAttack(this, EntityHuman.class, 1.0D, false));
    .
     
  13. Offline

    milkymilkway

    How do I change the attack distance of a spider? Like instead of a player having to be close. He can be like 40 blocks away. Kinda like a Zombie? In Craftbukkit 1.7.9. I can't figure it out for the life of me.
     
  14. Offline

    Garris0n

  15. Offline

    milkymilkway

  16. Offline

    Garris0n

    What exactly did you do?
     
  17. Offline

    milkymilkway

    Hey man, do you know how to disable the zombies from igniting through NMS?
     
  18. Offline

    Garris0n

    Entities actually have a fireproof tag built in.
     
  19. Offline

    flyguy23ndm

    Thanks for making this. I've never used NMS before and this is a great help.
    The only question I have is if there's a clean way to only add your mobs when you want to spawn them. but that's all.
     
  20. Offline

    milkymilkway

    Doesn't work very well. The Zombie flicker on and off. Any other ideas?? thanks
     
  21. Offline

    Garris0n

    Ask Mojang really nicely to disable the client prediction.

    In other words, no, not really.
     
  22. Offline

    milkymilkway

    Yeah, thanks for the sarcasm.
     
  23. Offline

    Suni

    TeeePeee Thanks for the great guide! I'm hoping to pursue to putting more spice in my server for my friends and I.

    Currently, I'm hoping to make a new difficulty for my server in which these custom mobs would be under the difficulty "Hell". My goal is to despawn the custom mobs and revert them back to their original entities if the difficulty is Peaceful/Easy/Normal/Hard.

    I was able to get custom monster working with changing stats around. However, I'm having a little problem with this part:
    The problems I'm running into is trying to despawning custom mobs and reverting it back to the original entities.

    I tried a small test for despawning for starters and I feel like I'm doing this horribly wrong. The code compiles fine, but crashes my Minecraft in less than a second when entering on my server. I am also unsure how to replace custom mobs with the original entities. Hoping if anyone may give me some leads?

    This code is located in my MainPlugin and called it in onEnable().

    Code:
    Show Spoiler
    Code:java
    1. public void despawner(){
    2. int numberOfMobs = Bukkit.getServer().getWorld("world").getEntities().size();
    3. for(int i = 0; i < numberOfMobs; i++){
    4. World world = ((CraftWorld) Bukkit.getWorld("world")).getHandle();
    5. List<Entity> entity = Bukkit.getServer().getWorld("world").getEntities();
    6. EntityType mob = entity.get(i).getType();
    7. if(mob.equals(EntityType.ZOMBIE)){
    8. CustomEntityZombie customZombie = new CustomEntityZombie(world);
    9. float health = customZombie.getMaxHealth();
    10. if(health == 300.0D)
    11. world.removeEntity(customZombie);
    12. }
    13. }
    14. }
    15. }
    16. }
    17. }
    18.  


    Thank yous \o
     
  24. Offline

    Giraffeknee

    Okay so I've set up my CustomEntityZombie class and it is working, but I'm not quite sure about two things.
    1) If the entity is a monster, how do we allow it to spawn in daylight.
    2) If the monster is in daylight, how do we stop it from burning.

    I can't even figure out which method is the spawning one for zombies. I see the world.addEntity(zombieentity) method called in damageEntity() method, and I've tried overriding that to ignore the light levels but it doesn't seem to be working...

    As for the fire, I've already tried to stop it from burning by overriding the e() and n() methods which set the zombie on fire (I believe) by removing the setOnFire() methods, but it isn't working at all.

    [Edit]
    For the fire part I set the super.fireProof = true in my constructor which effectively stops the fire damage, but it just flickers constantly (which is ugly). But at least that is solved.
     
  25. Offline

    Giraffeknee

    Never mind fixed it up.

    But I do have another question, is it possible to make custom entities that don't spawn in a certain biome naturally, spawn in that biome? (Example: CustomEntityPigZombie spawning in normal world biomes)

    TeeePeee
    Sorry for tagging, I just need to know urgently.

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: Jan 25, 2016
  26. Offline

    Pacothegint

    How would I get my Custom Zombie to drop different items?
    Would I use
    Code:java
    1.  
    2. protected Item getLoot() {
    3. return Items.ROTTEN_FLESH;
    4. }
    5.  

    Also how could I possibly make it so that all aggressive mobs and passive/neutral mobs are replaced by a zombie?
    Like say I want a skeleton to be replaced by a different toughness/speed zombie than that of a regular zombie and so on and so forth
     
  27. Offline

    TeeePeee

    Pacothegint
    To get it to drop different items, you can perform a switch on a random number (to drop one of many random items) or just return a different kind of item (check out the IDE suggestions for Items.)

    You can override a skeleton with a zombie too. In fact, you can just add an entry for every Minecraft mob with the same custom mob (ie. it is not EntityType dependant).
     
  28. Offline

    Pacothegint

    TeeePeee
    For some reason I keep getting a nullpointer exception on my client when connected to my Dev server.

    this is the stacktrace
    Code:
    Stacktrace:
        at bjf.a(SourceFile:289)
        at bao.b(SourceFile:1972)
        at bao.f(SourceFile:742)
        at net.minecraft.client.main.Main.main(SourceFile:148)
    
    any ideas?
     
  29. TeeePeee How would you go about creating a zombie-based custom entity, but not overriding the default zombies?
     
  30. Offline

    _Filip

    BorisTheTerrible create a zombie entity then modify it using the available methods.
     
Thread Status:
Not open for further replies.

Share This Page