1.12.2 I create a entity but it's invisible

Discussion in 'Spigot Plugin Development' started by lvhaoxuan, Feb 14, 2020.

  1. I use this code to create a entity.
    I spawn it but it's invisible and the AI is working correctly.
    I'm sure that I didn't give it invisible potion.
    In spigot 1.13.2,it's visible.
    In spigot 1.12.1,it's invisible
    I use EntitySpawnEvent to replace old zombie.
    I know it's because I forget to register it..........................
    spawn code:
    Code (Text):
        public DoomsdayZombie spawnDoomsdayZombie(Location loc) {
            DoomsdayZombie dz = new DoomsdayZombie(loc);
            CraftWorld craftWorld = (CraftWorld) loc.getWorld();
            craftWorld.addEntity(dz, CreatureSpawnEvent.SpawnReason.CUSTOM);
            return dz;
        }
    entity code:
    Code (Text):
    public class DoomsdayZombie extends EntityZombie {

        public ZombieTaskHandleStack taskHandle;
        public static Double movementSpeed;
        public ZombieAction action = ZombieAction.Avaiable;
        public DoomsdaySurvival plugin;
        public int stopCount = 0;
        public double last_X, last_Z;

        static {
            movementSpeed = Config.DOOMSDAY_ZOMBIE_SPEED;
        }

        public DoomsdayZombie(Location loc) {
            super(((CraftWorld) loc.getWorld()).getHandle());
            this.plugin = DoomsdaySurvival.plugin;
            setPosition(loc.getX(), loc.getY(), loc.getZ());
            taskHandle = new ZombieTaskHandleStack(plugin, this);
        }

        @Override
        protected void initAttributes() {
            super.initAttributes();
            getAttributeInstance(GenericAttributes.maxHealth).setValue(Config.DOOMSDAY_ZOMBIE_HEALTH);
            getAttributeInstance(GenericAttributes.MOVEMENT_SPEED).setValue(movementSpeed);
            getAttributeInstance(GenericAttributes.FOLLOW_RANGE).setValue(Config.DOOMSDAY_ZOMBIE_FOLLOWRANGE);
            getAttributeInstance(GenericAttributes.ATTACK_DAMAGE).setValue(Config.DOOMSDAY_ZOMBIE_DAMAGE);
        }

        public boolean isSameWorldWithTarget() {
            return getBukkitEntity().getWorld().getName().equals(getTarget().getWorld().getName());
        }

        public Location getLocation() {
            return ((org.bukkit.entity.Zombie) getBukkitEntity()).getLocation().clone();
        }

        public ZombieAction getAction() {
            return action;
        }

        public boolean isSameHeightWithTarget() {
            return hasTarget() && Math.abs(getTarget().getLocation().getY() - locY) <= 0.5;
        }

        public void ifStop() {
            if (stopCount == 0) {
                last_X = locX;
                last_Z = locZ;
            }
            stopCount++;
            if (stopCount == 60) {
                stopCount = 0;
                if (getXZDistance(last_X, last_Z, locX, locZ) < 0.5 && action == ZombieAction.Avaiable) {
                    stop();
                } else {
                    avaiable();
                }
            }
        }

        public void stop() {
            action = ZombieAction.Stop;
            goalSelector = new PathfinderGoalSelector((world != null) && (world.methodProfiler != null) ? world.methodProfiler : null);
            goalSelector.a(0, new PathfinderGoalFloat(this));
            targetSelector = new PathfinderGoalSelector((world != null) && (world.methodProfiler != null) ? world.methodProfiler : null);
        }

        public void avaiable() {
            action = ZombieAction.Avaiable;
            goalSelector = new PathfinderGoalSelector((world != null) && (world.methodProfiler != null) ? world.methodProfiler : null);
            goalSelector.a(0, new PathfinderGoalFloat(this));
            goalSelector.a(1, new PathfinderGoalZombieAttack(this, 1.0D, false));
            goalSelector.a(1, new DoomsdayZombieBreakPathfinderGoal(this));
            goalSelector.a(1, new DoomsdayZombiePlacePathfinderGoal(this));
            targetSelector = new PathfinderGoalSelector((world != null) && (world.methodProfiler != null) ? world.methodProfiler : null);
            targetSelector.a(2, new PathfinderGoalNearestAttackableTarget(this, EntityHuman.class, true));
            if (world.spigotConfig.zombieAggressiveTowardsVillager) {
                targetSelector.a(3, new PathfinderGoalNearestAttackableTarget(this, EntityVillager.class, false));
            }

        }

        @Override
        public void B_() {
            if (hasTarget()) {
                ifStop();
                if (!isBlockPassable(taskHandle.getHeadBlock().getRelative(BlockFace.DOWN))) {
                    taskHandle.push(new BlockTask(taskHandle.getHeadBlock().getRelative(BlockFace.DOWN)));
                }
                if (!isBlockPassable(taskHandle.getHeadBlock())) {
                    taskHandle.push(new BlockTask(taskHandle.getHeadBlock()));
                }
                if (getTarget().getLocation().getY() - locY > 0.5 && (action == ZombieAction.Stop || getXZDistance(getTarget().getLocation(), this.getBukkitEntity().getLocation()) < 7)) {
                    stop();
                    Location loc = getLocation();
                    setPosition(loc.getBlockX() + 0.5, locY, loc.getBlockZ() + 0.5);
                    if (!isBlockPassable(taskHandle.getBlockOnHead())) {
                        taskHandle.push(new BlockTask(taskHandle.getBlockOnHead()));
                    } else {
                        BlockTask task = new BlockTask(loc, 1);
                        task.isUp = true;
                        taskHandle.push(task);
                    }
                } else {
                    if (locY - getTarget().getLocation().getY() > 1 && getXZDistance(bukkitEntity.getLocation(), getTarget().getLocation()) < 5 && isInWater()) {
                        Location loc = getLocation().subtract(0, 1, 0);
                        taskHandle.push(new BlockTask(loc.getBlock()));
                        motY = -movementSpeed;
                        avaiable();
                    } else if (locY - getTarget().getLocation().getY() > 1 && getXZDistance(bukkitEntity.getLocation(), getTarget().getLocation()) < 0.3) {
                        Location loc = getLocation().subtract(0, 1, 0);
                        taskHandle.push(new BlockTask(loc.getBlock()));
                        avaiable();
                    } else if (isSameHeightWithTarget() || getTarget().getLocation().getY() - locY > 1 && action == ZombieAction.Stop) {
                        avaiable();
                    }
                }
            } else {
                avaiable();
                foundTarget();
            }
            taskHandle.doTick();
            super.B_();
        }

        public static Block getNMSBlock(CraftBlock b) {
            return (Block) NBT.doMethod(b, "getNMSBlock");
        }

        public static IBlockData getBlockNMS(CraftBlock b) {
            return (IBlockData) NBT.doMethod(b, "getData0");
        }

        public static boolean isBlockPassable(org.bukkit.block.Block b) {
            return b.isEmpty();
        }

        public void foundTarget() {
            if (!hasTarget()) {
                for (org.bukkit.entity.Entity en : bukkitEntity.getNearbyEntities(Config.DOOMSDAY_ZOMBIE_FOLLOWRANGE, Config.DOOMSDAY_ZOMBIE_FOLLOWRANGE, Config.DOOMSDAY_ZOMBIE_FOLLOWRANGE)) {
                    if (en instanceof org.bukkit.entity.LivingEntity) {
                        if (en instanceof org.bukkit.entity.Player) {
                            if (((org.bukkit.entity.Player) en).getGameMode() != GameMode.CREATIVE) {
                                setTarget((LivingEntity) en);
                                return;
                            }
                        }
                        if (en instanceof org.bukkit.entity.Villager || en instanceof org.bukkit.entity.IronGolem) {
                            setTarget((LivingEntity) en);
                            return;
                        }
                    }
                }
            }
        }

        public static double getXZDistance(double x1, double z1, double x2, double z2) {
            return Math.sqrt((x1 - x2) * (x1 - x2)
                    + (z1 - z2) * (z1 - z2));
        }

        public static double getXZDistance(Location loc1, Location loc2) {
            return Math.sqrt((loc1.getX() - loc2.getX()) * (loc1.getX() - loc2.getX())
                    + (loc1.getZ() - loc2.getZ()) * (loc1.getZ() - loc2.getZ()));
        }

        public org.bukkit.entity.LivingEntity getTarget() {
            return ((org.bukkit.entity.Zombie) getBukkitEntity()).getTarget();
        }

        public boolean hasTarget() {
            if (((org.bukkit.entity.Zombie) getBukkitEntity()).getTarget() != null) {
                if (!((org.bukkit.entity.Zombie) getBukkitEntity()).getTarget().isDead() && isSameWorldWithTarget()) {
                    return true;
                }
            }
            return false;
        }

        public void setTarget(org.bukkit.entity.LivingEntity le) {
            ((org.bukkit.entity.Zombie) getBukkitEntity()).setTarget(le);
        }

        @Override
        public void n() {
            goalSelector.a(0, new PathfinderGoalFloat(this));
            goalSelector.a(1, new PathfinderGoalZombieAttack(this, 1.0D, false));
            targetSelector.a(2, new PathfinderGoalNearestAttackableTarget(this, EntityHuman.class, true));
            if (world.spigotConfig.zombieAggressiveTowardsVillager) {
                targetSelector.a(3, new PathfinderGoalNearestAttackableTarget(this, EntityVillager.class, false));
            }
            goalSelector.a(1, new DoomsdayZombieBreakPathfinderGoal(this));
            goalSelector.a(1, new DoomsdayZombiePlacePathfinderGoal(this));
        }

        public enum ZombieAction {
            Avaiable,
            Stop;
        }
    }
     
     
    #1 lvhaoxuan, Feb 14, 2020
    Last edited: Feb 14, 2020
  2. Why are you using those methods instead of the World#spawnEntity inside the bukkit api?
     
  3. I think World#spawnEntity can't be used for spawning NMS entity
     
  4. You can use it but you need to use NMS.getBukkitEntity()