[Feedback] Mob Pathfinding + Goals

Discussion in 'Plugin Development' started by LusciousPear, Feb 22, 2011.

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

    LusciousPear

    Hey amigos,

    I'm embarking on a new mod, and I want to make sure I'm not duplicating any efforts here.

    The "big picture" is that I'm making mobs smarter, with pathfinding, group consensus, and goals (blow up wall X till you can get through, fire arrows at torches to extinguish them [already done]), etc.

    Has anyone made decent group pathfinding in another mod I can collaborate on?

    I have the chops to code this (I've written complex software for a decade), but I don't want to waste time :)
     
  2. Offline

    Afforess

    No one has done anything close to this. There was a single player mode called "Nightmare Mode" but all it did was allow mobs to spot you from farther away and through walls. Nothing too sophisticated.

    I've been secretly hoping for a mode like this for ages. Would finally force players to build real defenses.
     
  3. Offline

    Abrupt

    oh my god, pathfinding. * shudders*

    not really sure where to begin with this one, but I'd love to see how this turns out
     
  4. Offline

    LusciousPear

    Thanks for the vote of confidence. The good thing is that the existing pathfinding code is basically nonexistence, so it's easy to rip out. A little harder to do it in a way that conforms with the Bukkit API.
     
  5. Offline

    Rhythmatic

    I am extremely excited about this plugin. Any word on the release status?
     
  6. Offline

    PrivateAlpha

  7. Offline

    Rhythmatic

    How's this coming? I'm still erect from the first time I read this thread.
     
  8. Offline

    Valrix

    I support this idea and would love to see it in action.
     
  9. Offline

    Alex Nolan

    Sounds like a great idea :D. If you do decide to start on it I'll try to collaborate on it with you if you would like.
     
  10. Offline

    Afforess

    If you wanted to do it in a way that conforms with bukkit, why not add new PathfindingEvents that get called when the AI updates?
     
    kroimon likes this.
  11. Offline

    kroimon

    Love your idea, LusciousPear, you would for sure be a hero for a lot of minecrafters (including me)!
    And if it's good, maybe the Mojang guys would love you, too ;-)
     
  12. Offline

    Carnes

    I have been working on pathfinding as well. It's for my first mod called "Siege". Just got it working this morning and needed to cry out "Look what i made!" to someone who might appreciate it. Currently it's just A-B pathfinding. I've yet to add more logic like if they get stuck or pushed into a hole (or that other poor guy who stepped into magma, eek).

     
  13. Offline

    fullwall

    Very nice :). Is this single or multiplayer though?
     
  14. Offline

    Carnes

    It is multi, running on the latest CB build. The only other plugins on the server are WorldEdit and a small plugin to prevent agro from monsters (for testing things only). The pathfinding can be CPU intensive over long distances and there is still lots of things to improve.

    I'm happy you think it is very nice.
     
  15. Offline

    fullwall

    It's not nice, its epic, especially since it's on multiplayer. I can see how the CPU usage would stack up though. Still, at least it's in a workable form :D. Plans for release?
     
  16. Offline

    Carnes

    I honestly don't know how to release a plugin yet and the monster pathfinding needs to be combined with more logic to set goals and targets.

    The end result is going to be largish 15-50 monster Sieges on "civilized" areas. Going to use Spiders as engineers of sorts to build wool structures that breach player walls and bridge over magma (and are removed after the siege). Don't want to use creepers because destroying people's property sucks, but it could be a setting. Skeletons need to form into firing lines and cover engineer spiders who are building. It should be playable in a week or two (hopefully!)

    It could be combined with NPCs like yours to make some cool city/castle defense type things.
     
  17. Offline

    fullwall

    Sounds awesome :). Too bad... I'm going away next week :S. Guess I'll see it when I get back.
     
  18. Offline

    Glycan

    This sounds cool. It would be intresting to maybe add new some new mobs (with sprout, or just take something that's already there and make it diffrent, possibly marking it somehow [maybe putting a block on it's head]), and then have the mobs take active warfare operations against you. Some mobs (builder zombies, spider engieres, etc), would build there base, while others might attack your own, using concepts like flank, etc. Possibly using something like dynamic combat, or even a full-out RPG system, or making your own. The new enderman might build traps, that would be fun. ;p (You could formally define a trap, shouldn't be to hard). If you want to be extreme, you could even make it so that the mobs have to gather resources the same way you do. Let the greifing of creepers begin!
     
  19. Offline

    LusciousPear

    This is actually still being worked on. It's all in Clojure, which makes expressing these algorithms much easier.

    It's actually rather difficult and it'll be a few months (since I have a company to run). But happy to incorporate other research.
     
    ktbanh and Shamebot like this.
  20. Offline

    ktbanh

    Would be an awesome development idea. :] There was something similar to this, but i'm not sure how it was executed, zombies destroyed block on spawn to get to player.
     
  21. Offline

    ArchmageInc

    Has there been any movement on this? I have recently started considering developing pathfinding methods for use with Bukkit. The clip above shows good progress.
     
  22. Offline

    obnoxint

    There must be some way to take advantage of the new mob-AI. If there is someone who has information or even made progress on this, post it here.
     
  23. Offline

    fullwall

    obnoxint - yes, there is. When I have time I'm thinking about doing a bleeding pull for it.
     
  24. Offline

    obnoxint

  25. Offline

    fullwall

    obnoxint - yes, that's for inbuilt pathfinding - although it's abstracted through Navigation now (all the methods are obfuscated though which makes it irritating to use).
     
  26. Offline

    Coryf88

    obnoxint This should work for 1.2.*. I have not tried compiling this nor testing it in-game.

    Wander Speeds
    • Chicken: 0.25F
    • Cow: 0.2F
    • Creeper: 0.2F
    • IronGolem: 0.16F
    • Mooshroom: 0.2F
    • Ocelot: 0.23F
    • Pig: 0.25F
    • PigZombie: 0.23F
    • Sheep: 0.23F
    • Skeleton: 0.25F
    • Snowman: 0.2F
    • Villager: 0.3F
    • Wolf: 0.3F
    • Zombie: 0.23F
    Code:java
    1. /**
    2.  * Move a living entity to a coordinate, with a custom speed.
    3.  * Note: Not all living entities will work with this. E.g. Ones that use the old pathfinding, like spiders.
    4.  *
    5.  * @param livingEntity The living entity to move
    6.  * @param x The x axis position
    7.  * @param y The y axis position
    8.  * @param z The z axis position
    9.  * @param speed The speed to move at
    10.  * @return True if it was accepted by the navigator, otherwise false.
    11.  */
    12. private boolean livingEntityMoveTo(LivingEntity livingEntity, double x, double y, double z, float speed) {
    13. return ((org.bukkit.craftbukkit.entity.CraftLivingEntity)livingEntity).getHandle().ak().a(x, y, z, speed);
    14. }


    On-Topic: Creating your own pathfinding with 1.2.*'s Navigation system should be fairly easy (in theory)

    Edit:
    • Removed the method without the speed paramater. After digging through source code more, I realized that there isn't a sure way to get a mob's default speed. E.g. A cow's wander speed is 0.2F, but the class variable that is used for the movement speed ("bb") isn't changed from the default value of 0.7F.
    • Added wander speeds for all mobs that use the Navigation system. (Mobs not listed use the old pathfinding and will not work with this method, though will work with this one)
    • Compiled and tested, works.
     
  27. Offline

    obnoxint

    I built against craftbukkit-1.2.3-R0.2-20120309.060300-11 and bukkit-1.2.3-R0.2-20120309.060135-6 and got a NoSuchFieldException. I'll continue testing...

    Edit: or rather not... there are so many fields of type float in the EntityLiving class...
    Coryf88 : do you remember the CraftBukkit build you used? I'll attach the code I alreade have to this post.

    Edit 2: It seems I'm not allowed to attach a file. This is the code:

    Plugin class:
    Show Spoiler
    Code:
    package net.obnoxint.mcdev.MoveTest;
    
    import java.lang.reflect.Field;
    import java.util.HashSet;
    import java.util.Set;
    
    import net.minecraft.server.EntityLiving;
    
    import org.bukkit.Bukkit;
    import org.bukkit.Location;
    import org.bukkit.command.Command;
    import org.bukkit.command.CommandSender;
    import org.bukkit.craftbukkit.entity.CraftLivingEntity;
    import org.bukkit.entity.LivingEntity;
    import org.bukkit.entity.Player;
    import org.bukkit.plugin.java.JavaPlugin;
    
    public class MoveTestPlugin extends JavaPlugin {
    
        private Set<LivingEntity> entities = new HashSet<>();
    
        public void addEntity(LivingEntity entity) {
            entities.add(entity);
        }
    
        public Set<LivingEntity> getEntities() {
            return new HashSet<>(entities);
        }
    
        @Override
        public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
            try {
                Player p = (Player) sender;
                Location l = p.getLocation();
                for (LivingEntity e : entities){
                    livingEntityMoveTo(e, l.getX(), l.getY(), l.getZ());
                }
                return true;
            }catch(Exception e){
                e.printStackTrace();
            }
            return false;
        }
        
        @Override
        public void onDisable() {}
    
        @Override
        public void onEnable() {
            Bukkit.getPluginManager().registerEvents(new MoveTestListener(this), this);
        }
    
        private boolean livingEntityMoveTo(LivingEntity livingEntity, double x, double y, double z) throws NoSuchFieldException, IllegalAccessException {
            Field moveSpeed = EntityLiving.class.getDeclaredField("moveSpeed");
            moveSpeed.setAccessible(true);
            return this.livingEntityMoveTo(livingEntity, x, y, z, moveSpeed.getFloat(((CraftLivingEntity) livingEntity).getHandle()));
        }
    
        private boolean livingEntityMoveTo(LivingEntity livingEntity, double x, double y, double z, float speed) {
            return ((CraftLivingEntity) livingEntity).getHandle().ak().a(x, y, z, speed);
        }
    
    }
    


    Listener class:
    Show Spoiler
    Code:
    package net.obnoxint.mcdev.MoveTest;
    
    import org.bukkit.event.EventHandler;
    import org.bukkit.event.Listener;
    import org.bukkit.event.entity.CreatureSpawnEvent;
    import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason;
    
    public class MoveTestListener implements Listener {
    
        private final MoveTestPlugin plugin;
    
        public MoveTestListener(MoveTestPlugin plugin) {
            this.plugin = plugin;
        }
    
        @EventHandler
        public void onCreatureSpawn(CreatureSpawnEvent event) {
            if (!event.isCancelled() && event.getSpawnReason() == SpawnReason.SPAWNER_EGG) {
                plugin.addEntity(event.getEntity());
            }
        }
    
    }
    
     

    Attached Files:

  28. Offline

    Coryf88

    obnoxint As I specified in my post, I had not compiled nor tested it.

    Sorry, the field name is "bb", not "moveSpeed". I was using MCP to assist with looking through the code and somehow got the field names mixed up.

    Also, the method without the speed parameter won't work as expected, read the Edit section of my previous post.
     
  29. Offline

    obnoxint

    The method works pretty well. I set up a small circular labyrinth and placed a sheep in the middle. The sheep was able to find its way through the labyrinth. But: when the sheep (or any other mob) decides to do something else (like eating grass) it will define a new target for its pathfinding. I was surprised as the sheep suddenly turned around and went the same way back :)

    To fix this, the method has to be called again. So... either (1) a task calls the method every few ticks or (2) a task monitors the target and resets it when the AI decides to set another target or (3) the AI has to be suspended until the sheep reaches its goal. The first method seems to be the easiest, the third method the most reliable. I know that method one and two are relatively simple to implement. The second one is the most elegant, in my opinion. About the third one I'm not sure if this is even possible.

    Another thing is the fact that all methods require building against CraftBukkit and/or messing around with the NMS package. Both are things I would prefer to avoid under any circumstances. fullwall , have you been thinking about the bleeding pull you spoke about, yet?

    Thanks so far.
     
  30. Offline

    Coryf88

    It should also be possible to create your own PathfinderGoal, add it to the entities' goalSelector, and use it to keep the entity from forgetting about reaching the destination. PathfinderGoalRandomStroll (EntityAIWander in MCP), is a fairly simple example which is used for the mobs wandering movement.
     
Thread Status:
Not open for further replies.

Share This Page