[TUT] Making a LivingEntity walk to a specific tile.

Discussion in 'Resources' started by Ivan, Apr 3, 2013.

Thread Status:
Not open for further replies.
  1. Little update, I actually managed to get this to work :)
    This is how I did it (set your own location in the targetLocation, NOTE: this distance from the entity cannot be too far):

    Code:java
    1. package com.yourpackage.pathfinder;
    2.  
    3. import org.bukkit.Bukkit;
    4. import org.bukkit.Location;
    5.  
    6. import net.minecraft.server.v1_6_R2.EntityCreature;
    7. import net.minecraft.server.v1_6_R2.PathEntity;
    8. import net.minecraft.server.v1_6_R2.PathfinderGoal;
    9.  
    10. public class PathfinderGoalWalktoTile extends PathfinderGoal {
    11.  
    12. private float speed;
    13. private EntityCreature entitycreature;
    14. private PathEntity path;
    15.  
    16. public PathfinderGoalWalktoTile(EntityCreature entitycreature, float speed){
    17. this.speed = speed;
    18. this.entitycreature = entitycreature;
    19. }
    20.  
    21. @Override
    22. public boolean a() {
    23. if(this.entitycreature.world.v()) {
    24. return false;
    25. }
    26.  
    27. Location targetLocation = new Location(Bukkit.getWorld("world"), -912, 34, 1266);
    28.  
    29. boolean flag = this.entitycreature.getNavigation().c();
    30.  
    31. this.entitycreature.getNavigation().b(false);
    32. this.path = this.entitycreature.getNavigation().a(targetLocation.getX(), targetLocation.getY(), targetLocation.getZ());
    33. this.entitycreature.getNavigation().b(flag);
    34.  
    35. return this.path != null;
    36. }
    37.  
    38. @Override
    39. public void c() {
    40. this.entitycreature.getNavigation().a(this.path, (double) this.speed);
    41. }
    42. }

    Please note this code is made with Bukkit version 1.6_R2, method names may change with updates.
    I hope it can help someone else :)
     
    Ivan likes this.
  2. Offline

    bballheat

    Do Ender Dragons not have path finders?
     
  3. By the way, it seems that it doesn't always works, strangely enough when you restart the bukkit server a couple of times it does, not sure why that is.

    Correct me if I'm wrong but I'm pretty sure Ender Dragons use a completely different pathfinding AI, changing that would require you to dig into the original minecraft server files
     
  4. Offline

    Ivan

    I had to dig in the server files too for this :p
     
  5. You are a little bit confused sir, you don't need protocollib for this. Protocollib is used for packets, not for this type of nms. On the other hand, no it's not possible to do this without referencing to craftbukkit. For those who are going to say remote entities: no remote entities is also version dependant.
     
  6. Completely forgot about that, thanks :)
     
  7. Offline

    bballheat

    Oh geez. I didn't think it could get anymore complicated hahaha
     
  8. Offline

    Ultimate_n00b

    Since you're overriding methods and such, there is not way to do this with something like reflection. I have seen ways of dynamically compiling new version through a ClassLoader or something, try googling it.
     
  9. Offline

    handyhacker

    Jeez... it actually seems like i'm a little bit too stupid for this...

    My code:
    Show Spoiler

    EntityController:
    Show Spoiler

    Code:java
    1. package handyhacker.BasicAdministration.Binary.WorldAdministration;
    2.  
    3. import org.bukkit.Location;
    4.  
    5. import net.minecraft.server.v1_6_R2.EntityCreature;
    6. import net.minecraft.server.v1_6_R2.PathfinderGoal;
    7.  
    8. public class EntityController extends PathfinderGoal{
    9.  
    10. Location loc;
    11. float speed;
    12. private EntityCreature ec;
    13. public EntityController(EntityCreature ec, float speed, Location loc) {
    14. this.ec = ec;
    15. this.speed = speed;
    16. this.loc = loc;
    17. }
    18.  
    19. @Override
    20. public boolean a() {
    21. if (this.ec.aH() >= 100) {
    22. return false;
    23. } else {
    24. return true;
    25. }
    26. }
    27.  
    28. @Override
    29. public void c() {
    30. this.ec.getNavigation().a(loc.getX(), loc.getY(), loc.getZ(), speed);
    31. }
    32.  
    33. }
    34.  


    ControlledZombie:
    Show Spoiler

    Code:java
    1. package handyhacker.TheLastSurvivors.Utils;
    2.  
    3. import java.lang.reflect.AccessibleObject;
    4.  
    5. import handyhacker.BasicAdministration.Binary.WorldAdministration.EntityController;
    6. import net.minecraft.server.v1_6_R2.EntityHuman;
    7. import net.minecraft.server.v1_6_R2.EntityZombie;
    8. import net.minecraft.server.v1_6_R2.PathfinderGoalBreakDoor;
    9. import net.minecraft.server.v1_6_R2.PathfinderGoalFloat;
    10. import net.minecraft.server.v1_6_R2.PathfinderGoalHurtByTarget;
    11. import net.minecraft.server.v1_6_R2.PathfinderGoalLookAtPlayer;
    12. import net.minecraft.server.v1_6_R2.PathfinderGoalMeleeAttack;
    13. import net.minecraft.server.v1_6_R2.PathfinderGoalMoveThroughVillage;
    14. import net.minecraft.server.v1_6_R2.PathfinderGoalMoveTowardsRestriction;
    15. import net.minecraft.server.v1_6_R2.PathfinderGoalNearestAttackableTarget;
    16. import net.minecraft.server.v1_6_R2.PathfinderGoalRandomLookaround;
    17. import net.minecraft.server.v1_6_R2.PathfinderGoalRandomStroll;
    18. import net.minecraft.server.v1_6_R2.World;
    19.  
    20. import org.bukkit.Location;
    21. import org.bukkit.craftbukkit.v1_6_R2.util.UnsafeList;
    22.  
    23. public class ControlledZombie extends EntityZombie {
    24.  
    25. public ControlledZombie(World world, Location loc, float speed) {
    26. super(world);
    27.  
    28. try {
    29.  
    30. java.lang.reflect.Field gsa = net.minecraft.server.v1_6_R2.PathfinderGoalSelector.class.getDeclaredField("a");
    31. ((AccessibleObject) gsa).setAccessible(true);
    32.  
    33.  
    34. gsa.set(this.goalSelector, new UnsafeList());
    35. gsa.set(this.targetSelector, new UnsafeList());
    36. } catch (SecurityException e) {
    37. e.printStackTrace();
    38. } catch (NoSuchFieldException e) {
    39. e.printStackTrace();
    40. e.printStackTrace();
    41. e.printStackTrace();
    42. }
    43.  
    44. this.goalSelector.a(0, new PathfinderGoalFloat(this));
    45. this.goalSelector.a(1, new PathfinderGoalBreakDoor(this));
    46. this.goalSelector.a(1, new EntityController(this, speed, loc));//this.bw can be replaced by a custom speed
    47. this.goalSelector.a(2, new PathfinderGoalMeleeAttack(this, EntityHuman.class, this.bh, false));
    48. this.goalSelector.a(4, new PathfinderGoalMoveTowardsRestriction(this, this.bh));
    49. this.goalSelector.a(5, new PathfinderGoalMoveThroughVillage(this, this.bh, false));
    50. this.goalSelector.a(6, new PathfinderGoalRandomStroll(this, this.bh));
    51. this.goalSelector.a(7, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 8.0F));
    52. this.goalSelector.a(7, new PathfinderGoalRandomLookaround(this));
    53. this.targetSelector.a(1, new PathfinderGoalHurtByTarget(this, true));
    54. this.targetSelector.a(2, new PathfinderGoalNearestAttackableTarget(this, EntityHuman.class, 0, true));
    55. }
    56. }
    57.  


    Where is use it and how:
    Show Spoiler
    Code:
    void spawnStartZombies() {
    Location ZombieSpawn1 = new Location(getServer().getWorld(WORLD), ZOMBIESPAWN1X, ZOMBIESPAWN1Y, ZOMBIESPAWN1Z);
    Location ZombieWalk1 = new Location(getServer().getWorld(WORLD), ZOMBIEWALK1X, ZOMBIESPAWN1Y, ZOMBIEWALK1Z);
    ControlledZombie cz1 = (ControlledZombie) getServer().getWorld(WORLD).spawnEntity(ZombieSpawn1, EntityType.ZOMBIE);
    cz1.setHealth(getRound() * 1);
    EntityController ec1 = new EntityController(cz1, 10.0F, ZombieWalk1);
    ec1.c();
    }
    


    Then bukkit says that ControlledZombie can't be cast to CraftZombie :eek:
    What actually makes sense... but what i'm gonna do about it?
     
  10. Offline

    MrOAriO

    My Problem too ^^
     
  11. Offline

    Ivan

    Are you guys extending CraftZombie?
     
  12. Offline

    handyhacker

    Naah,
    i'm extending EntityZombie...
     
  13. So.. I have created an PathEntity using the A* Pathfinding algorithm, and it contains around 200 PathPoints but the zombies keep attempting to walk to the first block (PathPoint) and eventually stop moving.

    Strangely enough when I create a PathEntity which contains about 5 PathPoints (which are each several blocks apart instead of right next each other due to the A*) they just follow the PathPoints perfectly.

    Anyone experienced this (or something similar) as well? if yes, how did you fix it?

    This is my code (note: EntityPath and EntityPathPoint are a custom extend on PathEntity and PathPoint):
    Code:java
    1. package com.yourpackage.example;
    2.  
    3. import net.minecraft.server.v1_6_R3.EntityCreature;
    4. import net.minecraft.server.v1_6_R3.PathfinderGoal;
    5.  
    6. public class PathfinderGoalWalktoTile extends PathfinderGoal {
    7.  
    8. private float speed;
    9. private EntityCreature entitycreature;
    10. private EntityPath path;
    11.  
    12. public PathfinderGoalWalktoTile(EntityCreature entitycreature, float speed, EntityPath path){
    13. this.speed = speed;
    14. this.entitycreature = entitycreature;
    15. this.path = path;
    16. }
    17.  
    18. @Override
    19. public boolean a() {
    20. boolean flag = this.entitycreature.getNavigation().c();
    21. this.entitycreature.getNavigation().b(false);
    22.  
    23. /*
    24.   Old, manual PathEntity instead of A* Algorithm PathEntity
    25.   this.path = new EntityPath(new EntityPathPoint[]{
    26.   new EntityPathPoint(-912, 34, 1266),
    27.   new EntityPathPoint(-924, 34, 1253),
    28.   new EntityPathPoint(-933, 34, 1244),
    29.   new EntityPathPoint(-947, 34, 1230),
    30.   new EntityPathPoint(-960, 34, 1218)
    31.   });
    32.   */
    33. this.entitycreature.getNavigation().b(flag);
    34.  
    35. return this.path != null;
    36. }
    37.  
    38. @Override
    39. public void c() {
    40. this.entitycreature.getNavigation().a(this.path, (double) this.speed);
    41. }
    42. }
     
  14. Offline

    xTrollxDudex

    Ivan
    Well. This is an overcomplicated way to NOT use the Navigation class :p
    PHP:
    //lets have a location called l and an entity you want to have walk called e
    Navigation nav = ((EntityInsentient)((CraftEntitye).getHandle()).getNavigation();
    nav.a(l.getX(), l.getY(), l.getZ(), 0.3f);
     
  15. Offline

    Ivan

    If I'm correct, that will just send him there but when something distracted him it would immediately go after that other thing.
     
    xTrollxDudex likes this.
  16. Ivan any idea why my custom zombie keeps walking to the first PathPoint instead of following the rest of the route?
     
  17. Offline

    pasow

    so is there an easy fix, or do we have to create a whole new mob class???
     
  18. Offline

    sunnydan

  19. We know about that plugin, I don't know what the exact reason was but using your own pathfinding may be harder to do, however it gives you way more control about the entity and it's actions and it also doesn't require you to depend on the plugin beeing updated.

    Just create a custom PathFinderGoal class, the first post in the tutorial contains an example as how to do this and somewhere at the start of the 2nd page I posted my code as well

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: May 31, 2016
  20. Offline

    ReidoII

    Having the same problem. Zombies will walk to the first location, and then just stand there. If I hit them, they will move to the new/next location. =\
     
  21. Offline

    Ivan

    Are you creating a path system?
     
  22. Attempting to, but as others are stating the system is acting weird when it comes to bumping into things and following the pathpoints..

    I haven't figured out yet what the cause is though, it's not helping that the results are different every time either, for example, I spawn 3 groups of zombies all using the a* pathfinding to generate their pathpoints, only 1 group moves but don't follow their pathpoints (either that or don't know how to turn and bump into things and stop moving).

    it's really confusing..

    The hitting them part is new for me, they don't seem to respond the same way for me, it's like they've gone totally brain-dead when they stay at the same pathpoint for a few ticks

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: May 31, 2016
  23. Offline

    jeremytrains

    Ivan
    I have added the pathfinder and everything, have cleared all other goals, and added logging statements to my pathfinder goal. I add the pathfinder and then nothing happens and other than the constructor, no methods are called. Do I have to do something to "enable" the goal other than goalSelector.a(), and if it is traveling to a location it should be in goalSelector and not targetSelector, correct?
     
  24. Offline

    Eagle_Eye_Magic

    Anybody know if clearing the pathfinders still works in 1.7? I keep getting an illegal access error on this right here, saying it can't set the goalSelector and targetSelector to Unsafe Lists.
    Code:java
    1. Field gsa = net.minecraft.server.v1_5_R2.PathfinderGoalSelector.class.getDeclaredField("a");
    2. gsa.setAccessible(true);
    3. gsa.set(this.goalSelector, new UnsafeList());
    4. gsa.set(this.targetSelector, new UnsafeList());
     
  25. Offline

    DSH105

    Make sure that you are accessing the field you intend to change. The obfuscation of NMS code changes every update, meaning that the "a" field may no longer be the List you need to access. The latest code can be found on the GitHub repository.
     
  26. Offline

    Eagle_Eye_Magic

    Yeah thanks, i figured out its 'b' now. Theres also 'c' though, another UnsafeList, that im still unsure whether i'll need it but for now it works.
     
  27. Offline

    DSH105

    b stores all goals, whereas c only stores goals which are being ticked/updated.
     
  28. Offline

    Block34

    Ivan I don't think the aH() method works for 1.7. What method would I use after this.entitycreature?
    Is this correct?
    Code:java
    1. @Override
    2. public boolean a(){
    3. if(this.entitycreature.ai() >= 100){
    4. return false;
    5. }
    6. }

    Also where would I go to check out the public boolean a() method. I tried searchinf Github net minecraft server and there isn't a class for PathfinderGoal.
     
  29. Offline

    CrystalxNeth

    I am looking into making a mob go back to their location if pushed away (like the Mineplex server list mobs). Would a good way to do this be to have a runnable that checks the mob's location every X seconds and if it does not match the location I want it to be use a pathfinder like this to tell it to go to the block?
     
  30. Offline

    pasow

    Might as well just teleport the mob back to that location.
     
Thread Status:
Not open for further replies.

Share This Page