Util Make a mob follow a player!

Discussion in 'Resources' started by JPG2000, Mar 30, 2015.

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

    JPG2000

    Hello!

    I couldn't find a simple way to make a mob follow a player, so I have decided to create my own. All this entails is a single method with no additional resources required. Now onto the code.

    Method to make a LivingEntity follow a player:
    Code:
    followPlayer(player, entity, 1.75)
    NOTE: 'player' is the Player object, 'entity' is the LivingEntity or mob, and 1.75 is the walk speed.

    The Actual Method:
    Code:
        public void followPlayer(Player player, LivingEntity entity, double d) {
            final LivingEntity e = entity;
            final Player p = player;
            final float f = (float) d;
            Bukkit.getScheduler().scheduleSyncRepeatingTask(this, new Runnable() {
                @Override
                public void run() {
                    ((EntityInsentient) ((CraftEntity) e).getHandle()).getNavigation().a(p.getLocation().getX(), p.getLocation().getY(), p.getLocation().getZ(), f);
                }
            }, 0 * 20, 2 * 20);
        }
    NOTE: Copy & paste this in any class you'd like to use it in. Also, this works on a scheduler;if this is in your main class, then it should work as it's written. If this isn't in your main class, replace "this" on line 5 with the instance of your plugin. Additionally, if you'd like to make the mob unfollow a player, save the taskID of the schedule inside the method into an ArrayList, and use Bukkit.getScheduler().cancelTask(id) to cancel from there.

    EXAMPLE:
    Code:
        public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
            if (label.equalsIgnoreCase("pig")) { //When a player does the '/pig' command
                Player player = (Player) sender;
             
                LivingEntity entity = player.getWorld().spawn(player.getLocation(), Pig.class); //Spawn a pig at the players location
             
                followPlayer(player, entity, 1.75); //Make that pig follow the player at 1.75 speed
            }
        }
    Also guys, I want to say that this works on NMS code. This means that the imports for this code has the exact version of the bukkit version you are referencing. If you are getting errors in console using this code, it most likely because you are compiling with a diffirent bukkit version than in your server...make sure that you are using the same bukkit version in your IDE than that in the server!

    That's it! If you enjoyed this tutorial, please like this post and check out my server Tunnels: www.caved.in and you can join via hub.caved.in
     
    Last edited: May 3, 2015
  2. Offline

    nverdier

    @JPG2000 Probably a good idea to use cmd.getName.equalIgnoreCase(...), just due to good practices.
     
  3. Offline

    ChipDev

    Isn't the point of the resource.
     
    JPG2000 likes this.
  4. Offline

    nverdier

    @ChipDev Well people who are new to the API might see this, and we don't want them to pick up bad practices...
     
    ZomBlade_Shadow and ChipDev like this.
  5. Offline

    Goblom

    There has been alot of this type of resource. But all pertain to using Pathfinders. This doesn't use the pathfinder which makes it unique. So, good job on this since its actually more understandable :)
     
    JPG2000 likes this.
  6. Offline

    JPG2000

    The actual navigation part wasn't my unique code, I got it from ten's of threads and implemented it my own way, but thanks for your support;)

    I'd also like to add that this is the first resource I've seen that use's a single method to track, and it's extremely small (only 1 method!) :D
     
    ChipDev likes this.
  7. Offline

    sgavster

    This is just mindblowing. Works great for the amount of code.. It can be laggy/glitchy but works for what I need it for. Thank you!
     
  8. Offline

    Europia79

    @JPG2000

    I would expand this to add stay() functionality.

    Also, one of the problems with this is the use of OBC and NMS code (I'm not suggesting that OBC or NMS code shouldn't be used, i'm just staying that people should be aware of the implications). So maybe add a DISCLAIMER at the bottom explaining this and/or create a library that hides the implementation details behind an abstraction layer.

    And to further elaborate on OBC and NMS (for those who don't know): OBC stands for org.bukkit.craftbukkit and NMS stands for net.minecraft.server. As an example, let's take a look at the OBC and NMS classes used here:

    Code:java
    1.  
    2. import net.minecraft.server.v1_7_R1.EntityInsentient;
    3. import net.minecraft.server.v1_7_R2.EntityInsentient;
    4. import net.minecraft.server.v1_7_R3.EntityInsentient;
    5. import net.minecraft.server.v1_7_R4.EntityInsentient;
    6. import net.minecraft.server.v1_8_R1.EntityInsentient;
    7. import net.minecraft.server.v1_8_R2.EntityInsentient;
    8.  
    9. import org.bukkit.craftbukkit.v1_8_R2.entity.CraftEntity;
    10. import org.bukkit.craftbukkit.v1_8_R1.entity.CraftEntity;
    11. import org.bukkit.craftbukkit.v1_7_R4.entity.CraftEntity;
    12. import org.bukkit.craftbukkit.v1_7_R3.entity.CraftEntity;
    13. import org.bukkit.craftbukkit.v1_7_R2.entity.CraftEntity;
    14. import org.bukkit.craftbukkit.v1_7_R1.entity.CraftEntity;


    Okay, so if you compile your plugins with this code against Craftbukkit 1.8.3 and the server is running Craftbukkit 1.8.1, then you will get a ClassDefNotFoundException.

    If anyone is interesting in accommodating for this problem: Here is an awesome article:
    http://bukkit.org/threads/support-multiple-minecraft-versions-with-abstraction-maven.115810/

    Anyways, like I said: I think it would be cool if this were expanded into a more object-oriented approach, where the object in question IS some kind of com.yourplugin.Entity. That way, you pass the LivingEntity via the constructor instead of the method. Then add stay() and overload follow() to allow for more options.
     
    JPG2000 likes this.
  9. Offline

    sethrem

    This is very resource intensive. You should create a tick scheduler system. It's very simple and very very nice for resources. All the big server do that. But other than that nice guide but, like you said there is a better way of doing this and I might share it if people want.
     
  10. Offline

    nverdier

    Ummm...
     
  11. Offline

    FisheyLP

    Why not a new BukkitRunnable{} to cancel the task if one of the entities are dead?
     
  12. Offline

    bronzzze

    Code:
              public void followPlayer(Player player, LivingEntity entity, double d) {
                    final LivingEntity e = entity;
                    final Player p = player;
                    final float f = (float) d;
                    Bukkit.getScheduler().scheduleSyncRepeatingTask(main, new Runnable() {
                        @Override
                        public void run() {
                            ((EntityInsentient) ((CraftEntity) e).getHandle()).getNavigation().a(p.getLocation().getX(), p.getLocation().getY(), p.getLocation().getZ(), f);
                        }
                    }, 0 * 20, 2 * 20);
              
    
        }
    
    Code:
    LivingEntity livingE = p.getWorld().spawn(
                            e.getClickedBlock().getLocation().add(0, 1, 0),
                            Horse.class);
                    Horse horse = (Horse) livingE;
        Player p = e.getPlayer();
    
    followPlayer(p, livingE, 2);
    There is no error. But in game its nothing happening
     
    Last edited: Apr 8, 2015
  13. Offline

    sgavster

  14. Offline

    bronzzze

    Oh sorry I used this and its not working
    Code:
    LivingEntity le = (LivingEntity) horse;
    I switched both because I am writing on phone sorry.
     
  15. Offline

    JPG2000

    Is the horse spawning? Also make sure "main" on line 5 is an instance of your plugin.
     
  16. Offline

    bronzzze

    Code:
                    Horse horse = p.getWorld().spawn(
                            e.getClickedBlock().getLocation().add(0, 1, 0),
                            Horse.class);
    Main instance
    Code:
        private Main main;
    
        public EggClickEvent(Main main) {
            this.main = main;
    
        }
    And nothing happen... No errors. Horse spawn And he is just waiting
     
  17. Offline

    JPG2000

    Make sure that it is an instance of your Plugin object and not a class. Make a static Object named Plugin and make plugin = this on your onEnable method.

    Also, check if the horse is over 16 blocks away from the player and if so teleport the mob. Use this code on a repeating task (or PlayerMoveEvent):
    Code:
    double distance = player.getLocation().distance(mob.getLocation());
                    if(distance > 20) {
                        mob.teleport(player.getLocation);
                    }
    
     
  18. Offline

    bronzzze

    Ye I already Fix this. So Is this methotd buggy? Beacuse I am not sure which one should I use for public plugin.
    I make it like this.
    Code:
    public class followPlayer extends BukkitRunnable{
        @SuppressWarnings("unused")
        private ZPets main;
    
        public followPlayer(ZPets main) {
            this.main = main;
    
        }
        Player p;
        LivingEntity e;
        float f;
       
          public followPlayer(Player player, LivingEntity entity, double d) {
              this.e = entity;
              this.p = player;
                this.f = (float) d;
          }
               
                public void run() {
                    ((EntityInsentient) ((CraftEntity) e).getHandle()).getNavigation().a(p.getLocation().getX(), p.getLocation().getY(), p.getLocation().getZ(), f);
                    if(!(e.isValid()) || e.isDead())
                  cancel();
                    if(Distance(p.getLocation(), e.getLocation()) > 20){
                        e.teleport(p.getLocation().add(1,0,1));
                        p.sendMessage("Teleported!");
                        if(!(e.isValid())|| e.isDead())return;
                    }
          }
                public double Distance(Location playerloc, Location entityloc){
                    double distance = playerloc.distance(entityloc);
                    return distance;
                }
    
    }
    
    Thanks for help.
     
  19. Offline

    JPG2000

    It shouldn't be buggy. And no problem
     
  20. Offline

    bronzzze

    How could I make mobs controllable with WASD any api or tutorial there?
     
  21. Offline

    JPG2000

    I'm not sure, but I'll lead you in the right direction. I haven't tried to do this yet, but I'd imagine all it would be is: catching the PlayerMoveEvent and setting the players velocity on the mob and soforth.
     
  22. Offline

    Agentleader1

    @JPG2000 Haha, I saw a tutorial somewhere deep in the Bukkit forums on making mobs move toward a specific tile. You made the whole thing look so easy XD
     
    JPG2000 likes this.
  23. Offline

    JPG2000

    If Util was helpful for you, please like it so I know it's useful!
     
Thread Status:
Not open for further replies.

Share This Page