Flying Entities and pathfinders - Help

Discussion in 'Spigot Plugin Development' started by Swords123456, Jun 11, 2018.

  1. Ok so i'm trying to make flying entities move to a specific location, eg: pigs. I was wondering how i could achieve this. I cant use bats as they dont follow my pathfinders for some reason. If there is no easy way can someone tell me how to use and edit the move method in the entities or a tutorial on how to use and edit the move method? Thanks
     
  2. Bump: Can anyone help me?
     
  3. Ok so i tried using bats. No errors it just strolls around. It wont go to the location. Here is my code.
    Code (Java):


    import net.minecraft.server.v1_12_R1.*;
    import org.bukkit.ChatColor;
    import org.bukkit.Location;

    import java.lang.reflect.Field;
    import java.util.LinkedHashSet;

    public class CustomBat extends EntityBat {

        private static CustomBat bat;

        public CustomBat(World world, Location loc, Location to) {
            super(world);

            setCustomName(ChatColor.RED + String.valueOf(to.getX()));
            setCustomNameVisible(true);

            this.setLocation(loc.getX(), loc.getY(), loc.getZ(), loc.getYaw(), loc.getPitch());

            LinkedHashSet<?> setB = (LinkedHashSet<?>) getPrivateField("b", PathfinderGoalSelector.class, goalSelector); setB.clear();
            LinkedHashSet<?> setC = (LinkedHashSet<?>) getPrivateField("c", PathfinderGoalSelector.class, goalSelector); setC.clear();

            this.goalSelector.a(0, new PathfinderGoalFloat(this));
            this.goalSelector.a(1, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 8.0F));
            this.goalSelector.a(3, new PathfinderGoalWalktoTile(this, to, 0.5F));
            bat = this;
        }

        public static Object getPrivateField(String fieldName, Class<PathfinderGoalSelector> clazz, Object object)
        {
            Field field;
            Object o = null;
            try
            {
                field = clazz.getDeclaredField(fieldName);
                field.setAccessible(true);
                o = field.get(object);
            }
            catch(NoSuchFieldException e)
            {
                e.printStackTrace();
            }
            catch(IllegalAccessException e)
            {
                e.printStackTrace();
            }
            return o;
        }

        public static CustomBat getBat() {
            return bat;
        }
    }
    Code (Text):

    import net.minecraft.server.v1_12_R1.*;
    import org.bukkit.Location;

    public class PathfinderGoalWalktoTile extends PathfinderGoal{

        private float speed;

        private EntityInsentient entity;

        private Location loc;

        private Navigation navigation;

        public PathfinderGoalWalktoTile(EntityInsentient entity, Location loc, float speed) {
            this.entity = entity;
            this.loc = loc;
            this.navigation = (Navigation) this.entity.getNavigation();
            this.speed = speed;
        }

        [USER=32110]@Override[/USER]
        public boolean a() {
            return true;
        }

        [USER=32110]@Override[/USER]
        public boolean b() {
            return false;
        }

        [USER=32110]@Override[/USER]
        public void c() {
            PathEntity pathEntity = this.navigation.a(loc.getX(), loc.getY(), loc.getZ());
            this.navigation.a(pathEntity, speed);
        }



    }
    Code (Java):
    package me.spirafy.utils;

    import net.minecraft.server.v1_12_R1.*;
    import org.bukkit.Location;
    import org.bukkit.craftbukkit.v1_12_R1.CraftWorld;
    import org.bukkit.entity.EnderDragon;
    import org.bukkit.entity.EntityType;

    import java.lang.reflect.Constructor;
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;

    public enum CustomEntities {

        JOINVILLAGER("JoinVillager", 120, EntityType.VILLAGER, EntityVillager.class, CustomVillager.class),
        DRAGONBUS("Dragon", 63, EntityType.ENDER_DRAGON, EntityEnderDragon.class, DragonBus.class),
        BAT("Bat", 65, EntityType.BAT, EntityBat.class, CustomBat.class);



        private static Method validateEntityMethod;

        static  {
            try {
                validateEntityMethod = World.class.getDeclaredMethod("b", Entity.class);
                validateEntityMethod.setAccessible(true);
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            }
        }

        private String name;
        private int id;
        private EntityType entityType;
        private Class<? extends Entity> nmsClass;
        private Class<? extends Entity> customClass;
        private MinecraftKey key;
        private MinecraftKey oldKey;

        private CustomEntities(String name, int id, EntityType entityType, Class<? extends Entity> nmsClass, Class<? extends Entity> customClass) {
            this.name = name;
            this.id = id;
            this.entityType = entityType;
            this.nmsClass = nmsClass;
            this.customClass = customClass;
            this.key = new MinecraftKey(name);
            this.oldKey = EntityTypes.b.b(nmsClass);
        }

        public static void registerEntities() { for (CustomEntities ce : CustomEntities.values()) ce.register(); }
        public static void unregisterEntities() { for (CustomEntities ce : CustomEntities.values()) ce.unregister(); }

        private void register() {
            EntityTypes.d.add(key);
            EntityTypes.b.a(id, key, customClass);
        }

        private void unregister() {
            EntityTypes.d.remove(key);
            EntityTypes.b.a(id, oldKey, nmsClass);
        }

        public void spawn(Location spawnLoc, Location to) {
            try {
                Constructor customClassConstructor = customClass.getConstructor(World.class, Location.class, Location.class);
                EntityLiving entity = (EntityLiving) customClassConstructor.newInstance(((CraftWorld) spawnLoc.getWorld()).getHandle(), spawnLoc, to);

                if(addEntityToWorld(((CraftWorld) spawnLoc.getWorld()).getHandle(), entity)) {
                    System.out.println("DEBUG: ADD ENTITY=TRUE");
                }
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
        }

        private boolean addEntityToWorld(WorldServer nmsWorld, Entity nmsEntity) {
            final int chunkX = MathHelper.floor(nmsEntity.locX / 16.0);
            final int chunkZ = MathHelper.floor(nmsEntity.locZ / 16.0);

            if (!nmsWorld.getChunkProviderServer().isLoaded(chunkX, chunkZ)) {
                nmsEntity.dead = true;
                return false;
            }

            nmsWorld.getChunkAt(chunkX, chunkZ).a(nmsEntity);
            nmsWorld.entityList.add(nmsEntity);

            try {
                validateEntityMethod.invoke(nmsWorld, nmsEntity);
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }

            return true;
        }

        public String getName() {
            return name;
        }

        public int getID() {
            return id;
        }

        public EntityType getEntityType() {
            return entityType;
        }

        public Class<?> getCustomClass() {
            return customClass;
        }
    }
     
     
  4. Ok same with ender dragon (Kind of). So how could i edit the bats move method to make it go into a certain direction?? I have no idea.
     
    #6 Swords123456, Jun 13, 2018 at 10:25 AM
    Last edited: Jun 13, 2018 at 11:21 AM
  5. Bats are ambient creatures. They don't target anything. They just randomly flop around hitting walls, floors, and ceilings trying to get away from players.

    If you want a flying mob with targeting capabilities (this is a requirement for the movement pathfinder you want) try using parrots.

    You could also try vex, but idk if them going through blocks is overridable (it might be, I never looked).

    If you're aiming for lower versions of Minecraft, I can't help. Join us in 2018 and get with the program ;)
     
  6. If you really want to use bats, you can override the method that does random movement every tick and implement your own movement. The NMS entity should have methods for moving itself.
     
  7. EnderDragons, ghasts are working. They are both Flying entities.
     
  8. ok trying parrots they slowly float to the ground. And not move to the location. I did find a pathfinder goal for flying. Have no idea how it works though.
    Code (Java):
    //
    // Source code recreated from a .class file by IntelliJ IDEA
    // (powered by Fernflower decompiler)
    //

    package net.minecraft.server.v1_12_R1;

    import java.util.Iterator;
    import javax.annotation.Nullable;
    import net.minecraft.server.v1_12_R1.BlockPosition.MutableBlockPosition;

    public class PathfinderGoalRandomFly extends PathfinderGoalRandomStrollLand {
        public PathfinderGoalRandomFly(EntityCreature var1, double var2) {
            super(var1, var2);
        }

        @Nullable
        protected Vec3D f() {
            Vec3D var1 = null;
            if (this.a.isInWater() || this.a.ap()) {
                var1 = RandomPositionGenerator.b(this.a, 15, 15);
            }

            if (this.a.getRandom().nextFloat() >= this.h) {
                var1 = this.j();
            }

            return var1 == null ? super.f() : var1;
        }

        @Nullable
        private Vec3D j() {
            BlockPosition var1 = new BlockPosition(this.a);
            MutableBlockPosition var2 = new MutableBlockPosition();
            MutableBlockPosition var3 = new MutableBlockPosition();
            Iterable var4 = MutableBlockPosition.b(MathHelper.floor(this.a.locX - 3.0D), MathHelper.floor(this.a.locY - 6.0D), MathHelper.floor(this.a.locZ - 3.0D), MathHelper.floor(this.a.locX + 3.0D), MathHelper.floor(this.a.locY + 6.0D), MathHelper.floor(this.a.locZ + 3.0D));
            Iterator var5 = var4.iterator();

            BlockPosition var6;
            boolean var8;
            do {
                do {
                    if (!var5.hasNext()) {
                        return null;
                    }

                    var6 = (BlockPosition)var5.next();
                } while(var1.equals(var6));

                Block var7 = this.a.world.getType(var3.g(var6).c(EnumDirection.DOWN)).getBlock();
                var8 = var7 instanceof BlockLeaves || var7 == Blocks.LOG || var7 == Blocks.LOG2;
            } while(!var8 || !this.a.world.isEmpty(var6) || !this.a.world.isEmpty(var2.g(var6).c(EnumDirection.UP)));

            return new Vec3D((double)var6.getX(), (double)var6.getY(), (double)var6.getZ());
        }
    }
     
    I tried before it didn`t work. Ill try again today
     
    #10 Swords123456, Jun 13, 2018 at 9:59 PM
    Last edited: Jun 14, 2018 at 6:44 AM
  9. Are you able tell me how i can make my own movement methods? I don't know and cant find tutorials.
     
  10. You can use the overridden random movement method for your code. Write some code using the entity's teleport method that moves it around. You'll need to use some vector math to calculate the next position you want to move to.
     

Share This Page