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
@ChipDev Well people who are new to the API might see this, and we don't want them to pick up bad practices...
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
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!)
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!
@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 import net.minecraft.server.v1_7_R1.EntityInsentient;import net.minecraft.server.v1_7_R2.EntityInsentient;import net.minecraft.server.v1_7_R3.EntityInsentient;import net.minecraft.server.v1_7_R4.EntityInsentient;import net.minecraft.server.v1_8_R1.EntityInsentient;import net.minecraft.server.v1_8_R2.EntityInsentient; import org.bukkit.craftbukkit.v1_8_R2.entity.CraftEntity;import org.bukkit.craftbukkit.v1_8_R1.entity.CraftEntity;import org.bukkit.craftbukkit.v1_7_R4.entity.CraftEntity;import org.bukkit.craftbukkit.v1_7_R3.entity.CraftEntity;import org.bukkit.craftbukkit.v1_7_R2.entity.CraftEntity;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.
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.
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
Oh sorry I used this and its not working Code: LivingEntity le = (LivingEntity) horse; I switched both because I am writing on phone sorry.
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
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); }
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.
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.
@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