NMS Entity - Custom Pathing does not actually fire

Discussion in 'Plugin Development' started by Dudemister1999, Oct 17, 2014.

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

    Dudemister1999

    Hello again! I've run into a problem I cannot for the life of me solve!

    Code:java
    1. package me.dudemister.deadworks.entities.ai;
    2.  
    3. import java.util.ArrayList;
    4. import java.util.List;
    5. import net.minecraft.server.v1_7_R4.EntityInsentient;
    6. import net.minecraft.server.v1_7_R4.EntityLiving;
    7. import net.minecraft.server.v1_7_R4.PathfinderGoalLeapAtTarget;
    8. import org.bukkit.Bukkit;
    9. import org.bukkit.Effect;
    10. import org.bukkit.Location;
    11. import org.bukkit.World;
    12. import org.bukkit.block.Block;
    13. import org.bukkit.entity.Entity;
    14. import org.bukkit.entity.LivingEntity;
    15.  
    16. public class PathfinderGoalStomp extends PathfinderGoalLeapAtTarget
    17. {
    18. EntityInsentient entity;
    19. EntityLiving target;
    20. float damageToDeal;
    21.  
    22. public PathfinderGoalStomp(EntityInsentient entity, float damage)
    23. {
    24. super(entity, damage);
    25.  
    26. this.entity = entity;
    27. this.damageToDeal = damage;
    28. }
    29.  
    30. @Override
    31. public boolean a()
    32. {
    33. if(entity.getGoalTarget() != null)
    34. {
    35. target = entity.getGoalTarget();
    36. }
    37. else
    38. {
    39. return false;
    40. }
    41.  
    42. double d = entity.f(target);
    43.  
    44. if ((d > 6.0D))
    45. {
    46. return false;
    47. }
    48.  
    49. if(!entity.onGround)
    50. {
    51. return false;
    52. }
    53.  
    54. if (target.aI().nextInt(5) != 0)
    55. {
    56. return false;
    57. }
    58. return true;
    59. }
    60.  
    61. @Override
    62. public boolean b()
    63. {
    64. return !entity.onGround;
    65. }
    66.  
    67. @Override
    68. public void c()
    69. {
    70. entity.motY += 1;
    71.  
    72. Location loc = new Location( Bukkit.getWorld(entity.world.getWorld().getName()), entity.locX, entity.locY, entity.locZ );
    73. World w = Bukkit.getWorld(entity.world.getWorld().getName());
    74.  
    75. List<Block> blocks = new ArrayList<>();
    76. int radius = 5;
    77.  
    78. {
    79. for (double x = -entity.locX + radius; x < entity.locX + radius; x++)
    80. for (double z = -entity.locZ + radius; z < entity.locZ + radius; z++)
    81. blocks.add(w.getBlockAt((int)x, (int)entity.locY, (int)z));
    82. }
    83.  
    84. for(Block b : blocks)
    85. {
    86. b.getWorld().playEffect(b.getLocation(), Effect.STEP_SOUND, b.getType().getId());
    87. }
    88.  
    89. for(Entity ent : entity.getBukkitEntity().getNearbyEntities(radius, 3, radius))
    90. {
    91. if(ent instanceof LivingEntity)
    92. {
    93. ((LivingEntity)ent).damage(damageToDeal, entity.getBukkitEntity());
    94. }
    95. }
    96. }
    97. }


    Code:java
    1. java.lang.NullPointerException: Ticking entity
    2. at me.dudemister.deadworks.entities.ai.PathfinderGoalStomp.a(PathfinderGoalStomp.java:30)
    3. at net.minecraft.server.v1_7_R4.PathfinderGoalSelector.a(PathfinderGoalSelector.java:70)
    4. at net.minecraft.server.v1_7_R4.EntityInsentient.bn(EntityInsentient.java:407)
    5. at net.minecraft.server.v1_7_R4.EntityLiving.e(EntityLiving.java:1535)
    6. at net.minecraft.server.v1_7_R4.EntityInsentient.e(EntityInsentient.java:289)
    7. at net.minecraft.server.v1_7_R4.EntityMonster.e(EntityMonster.java:21)
    8. at net.minecraft.server.v1_7_R4.EntityZombie.e(EntityZombie.java:160)
    9. at net.minecraft.server.v1_7_R4.EntityLiving.h(EntityLiving.java:1398)
    10. at net.minecraft.server.v1_7_R4.EntityInsentient.h(EntityInsentient.java:150)
    11. at net.minecraft.server.v1_7_R4.EntityMonster.h(EntityMonster.java:25)
    12. at net.minecraft.server.v1_7_R4.EntityZombie.h(EntityZombie.java:231)
    13. at net.minecraft.server.v1_7_R4.World.entityJoinedWorld(World.java:1418)
    14. at net.minecraft.server.v1_7_R4.World.playerJoinedWorld(World.java:1396)
    15. at net.minecraft.server.v1_7_R4.World.tickEntities(World.java:1281)
    16. at net.minecraft.server.v1_7_R4.WorldServer.tickEntities(WorldServer.java:481)
    17. at net.minecraft.server.v1_7_R4.MinecraftServer.v(MinecraftServer.java:649)
    18. at net.minecraft.server.v1_7_R4.DedicatedServer.v(DedicatedServer.java:258)
    19. at net.minecraft.server.v1_7_R4.MinecraftServer.u(MinecraftServer.java:558)
    20. at net.minecraft.server.v1_7_R4.MinecraftServer.run(MinecraftServer.java:469)
    21. at net.minecraft.server.v1_7_R4.ThreadServerApplication.run(SourceFile:628)
    22.  
    23. -- Entity being ticked --
    24. Details:
    25. Entity Type: Zombie (me.dudemister.deadworks.entities.DeadworksZombie)
    26. Entity ID: 194
    27. Entity Name: Zombie
    28. Entity's Exact location: 255.30, 82.25, -1586.50
    29. Entity's Block location: World: (255,82,-1587), Chunk: (at 15,5,13 in 15,-100; contains blocks 240,0,-1600 to 255,255,-1585), Region: (0,-4; contains chunks 0,-128 to 31,-97, blocks 0,0,-2048 to 511,255,-1537)
    30. Entity's Momentum: 0.00, 0.00, 0.00


    Thank you for helping!
    -Hydroxocobalamin (OCHbl)

    *EDIT* Alright, I fixed the problem and updated the code. No error, now it just doesn't work.
     
  2. Offline

    xTrollxDudex

    Debug booleans or watch stack for proper method calls
     
  3. Offline

    Europia79

    Dudemister1999

    Increase the radius for testing purposes. If it works, then you can make it smaller again. Also, add debugging lines.

    Also, I changed some of your loops: I'm not sure why you wanted to do 5 minus X ? Maybe it was a mistake ? I changed it to X - 10 and Z - 10.

    Finally, show the class that uses the PathFinder. And show the code that registers the custom entity.

    Code:java
    1. package me.dudemister.deadworks.entities.ai;
    2.  
    3. import java.util.ArrayList;
    4. import java.util.List;
    5. import net.minecraft.server.v1_7_R4.EntityInsentient;
    6. import net.minecraft.server.v1_7_R4.EntityLiving;
    7. import net.minecraft.server.v1_7_R4.PathfinderGoalLeapAtTarget;
    8. import org.bukkit.Bukkit;
    9. import org.bukkit.Effect;
    10. import org.bukkit.Location;
    11. import org.bukkit.World;
    12. import org.bukkit.block.Block;
    13. import org.bukkit.entity.Entity;
    14. import org.bukkit.entity.LivingEntity;
    15.  
    16. public class PathfinderGoalStomp extends PathfinderGoalLeapAtTarget
    17. {
    18. EntityInsentient entity;
    19. EntityLiving target;
    20. float damageToDeal;
    21.  
    22. public PathfinderGoalStomp(EntityInsentient entity, float damage)
    23. {
    24. super(entity, damage);
    25.  
    26. this.entity = entity;
    27. this.damageToDeal = damage;
    28. }
    29.  
    30. @Override
    31. public boolean a()
    32. {
    33. if(entity.getGoalTarget() != null)
    34. {
    35. target = entity.getGoalTarget();
    36. }
    37. else
    38. {
    39. return false;
    40. }
    41.  
    42. double d = entity.f(target);
    43.  
    44. if ((d > 6.0D))
    45. {
    46. return false;
    47. }
    48.  
    49. if(!entity.onGround)
    50. {
    51. return false;
    52. }
    53.  
    54. if (target.aI().nextInt(5) != 0)
    55. {
    56. return false;
    57. }
    58. return true;
    59. }
    60.  
    61. @Override
    62. public boolean b()
    63. {
    64. return !entity.onGround;
    65. }
    66.  
    67. @Override
    68. public void c()
    69. {
    70. entity.motY += 1;
    71.  
    72. Location loc = new Location( Bukkit.getWorld(entity.world.getWorld().getName()), entity.locX, entity.locY, entity.locZ );
    73. World w = Bukkit.getWorld(entity.world.getWorld().getName());
    74.  
    75. List<Block> blocks = new ArrayList<>();
    76. int radius = 10;
    77.  
    78. {
    79. for (double x = entity.locX - radius; x < entity.locX + radius; x++)
    80. for (double z = entity.locZ - radius; z < entity.locZ + radius; z++)
    81. blocks.add(w.getBlockAt((int)x, (int)entity.locY, (int)z));
    82. }
    83.  
    84. for(Block b : blocks)
    85. {
    86. b.getWorld().playEffect(b.getLocation(), Effect.STEP_SOUND, b.getType().getId());
    87. }
    88.  
    89. for(Entity ent : entity.getBukkitEntity().getNearbyEntities(radius, radius, radius))
    90. {
    91. if(ent instanceof LivingEntity)
    92. {
    93. ((LivingEntity)ent).damage(damageToDeal, entity.getBukkitEntity());
    94. }
    95. }
    96. }
    97. }


    I have some custom mob code here (if you wanna take a look):
    https://github.com/Europia79/Extrac...es/v1_7_R1/src/mc/euro/extraction/nms/v1_7_R1

    Also, there's a good tutorial here:
    http://forums.bukkit.org/threads/nms-tutorial-how-to-override-default-minecraft-mobs.216788/

    Good luck!
     
  4. Offline

    MexMaster

    Just wanted to say, that you don't have to create a custom entity (or custom pathfinder goal) for moving entities around, you can also use their navigation, I like my idea more but it's your decision.
    If I understood everything right
     
  5. Offline

    Dudemister1999

    MexMaster *EDIT*

    I meant giant, not ghast. My bad. :p

    Europia79

    Entity code
    Show Spoiler

    Code:java
    1. import me.dudemister.deadworks.entities.ai.PathfinderGoalStomp;
    2. import net.minecraft.server.v1_7_R4.EntityGiantZombie;
    3. import net.minecraft.server.v1_7_R4.EntityHuman;
    4. import net.minecraft.server.v1_7_R4.GenericAttributes;
    5. import net.minecraft.server.v1_7_R4.PathfinderGoalNearestAttackableTarget;
    6. import net.minecraft.server.v1_7_R4.World;
    7.  
    8. public class DeadworksGiant extends EntityGiantZombie
    9. {
    10. public DeadworksGiant(World world)
    11. {
    12. super(world);
    13.  
    14. this.targetSelector.a(2, new PathfinderGoalNearestAttackableTarget(this, EntityHuman.class, 0, true));
    15. this.targetSelector.a(2, new PathfinderGoalStomp(this, 12.0F));
    16. }
    17.  
    18. @Override
    19. public void aD()
    20. {
    21. this.getAttributeMap().a(GenericAttributes.maxHealth);
    22. this.getAttributeMap().a(GenericAttributes.d);
    23. this.getAttributeMap().a(GenericAttributes.e);
    24. getAttributeInstance(GenericAttributes.maxHealth).setValue(60.0D);
    25. getAttributeInstance(GenericAttributes.d).setValue(0.5D);
    26. getAttributeInstance(GenericAttributes.e).setValue(50.0D);
    27. }
    28. }



    Registry code
    Show Spoiler

    Code:java
    1. public void overrideEntity(String mobName, int mobID, Class<? extends EntityInsentient> oldClass, Class<? extends EntityInsentient> customClass)
    2. {
    3. try
    4. {
    5. List<Map<?, ?>> dataMaps = new ArrayList<Map<?, ?>>();
    6. for (Field f : EntityTypes.class.getDeclaredFields())
    7. {
    8. if (f.getType().getSimpleName().equals(Map.class.getSimpleName()))
    9. {
    10. f.setAccessible(true);
    11. dataMaps.add((Map<?, ?>) f.get(null));
    12. }
    13. }
    14.  
    15. if (dataMaps.get(2).containsKey(mobID))
    16. {
    17. dataMaps.get(0).remove(mobName);
    18. dataMaps.get(2).remove(mobID);
    19. }
    20.  
    21. Method method = EntityTypes.class.getDeclaredMethod("a", Class.class, String.class, int.class);
    22. method.setAccessible(true);
    23. method.invoke(null, customClass, mobName, mobID);
    24.  
    25. for (Field f : BiomeBase.class.getDeclaredFields())
    26. {
    27. if (f.getType().getSimpleName().equals(BiomeBase.class.getSimpleName()))
    28. {
    29. if (f.get(null) != null)
    30. {
    31. for (Field list : BiomeBase.class.getDeclaredFields())
    32. {
    33. if (list.getType().getSimpleName().equals(List.class.getSimpleName()))
    34. {
    35. list.setAccessible(true);
    36. @SuppressWarnings("unchecked")
    37. List<BiomeMeta> metaList = (List<BiomeMeta>) list.get(f.get(null));
    38.  
    39. for (BiomeMeta meta : metaList)
    40. {
    41. Field clazz = BiomeMeta.class.getDeclaredFields()[0];
    42. if (clazz.get(meta).equals(oldClass))
    43. {
    44. clazz.set(meta, customClass);
    45. }
    46. }
    47. }
    48. }
    49.  
    50. }
    51. }
    52. }
    53.  
    54. }
    55. {
    56. e.printStackTrace();
    57. }
    58. }


    Actual registration:
    Show Spoiler

    Code:java
    1. public void registerEntities()
    2. {
    3. EntityManager em = DeadworksAPI.getEntityManager();
    4.  
    5. em.overrideEntity("Zombie", 54, EntityZombie.class, DeadworksZombie.class);
    6. em.overrideEntity("Giant", 53, EntityGiantZombie.class, DeadworksGiant.class);
    7. em.overrideEntity("Ghast", 56, EntityGhast.class, DeadworksBoss_Ghast.class);
    8. }



    The entity is registered, and he works, just the AI does not function. I'll try your code out, thanks.

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

    Europia79


    i didn't know you could that.
     
  7. Offline

    Dudemister1999

    Europia79 Yep! I just can't in this project.
     
  8. Offline

    Europia79

    Dudemister1999

    instead of this.targetSelector.a()

    try this
    Code:java
    1. this.goalSelector.a(2, new PathfinderGoalStomp(this, 12.0F));


    Lemme know if that works, or if you find another solution.
     
  9. Offline

    Dudemister1999

    Europia79 Well, they aren't spawning anymore... but no errors! ^^
     
Thread Status:
Not open for further replies.

Share This Page