隔壁老吕
本帖最后由 隔壁老吕 于 2020-2-14 11:21 编辑

生成后无法看见实体,但是AI工作正常。(没有给它隐形药水效果)
在spigot1.13.2中,它是可见的。
在1.12.1中,它是看不见的
用EntitySpawnEvent替换原版僵尸。

生成代码:
  1.     public DoomsdayZombie spawnDoomsdayZombie(Location loc) {
  2.         DoomsdayZombie dz = new DoomsdayZombie(loc);
  3.         CraftWorld craftWorld = (CraftWorld) loc.getWorld();
  4.         craftWorld.addEntity(dz, CreatureSpawnEvent.SpawnReason.CUSTOM);
  5.         return dz;
  6.     }
复制代码

实体代码:
  1. public class DoomsdayZombie extends EntityZombie {

  2.     public ZombieTaskHandleStack taskHandle;
  3.     public static Double movementSpeed;
  4.     public ZombieAction action = ZombieAction.Avaiable;
  5.     public DoomsdaySurvival plugin;
  6.     public int stopCount = 0;
  7.     public double last_X, last_Z;

  8.     static {
  9.         movementSpeed = Config.DOOMSDAY_ZOMBIE_SPEED;
  10.     }

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

  17.     @Override
  18.     protected void initAttributes() {
  19.         super.initAttributes();
  20.         getAttributeInstance(GenericAttributes.maxHealth).setValue(Config.DOOMSDAY_ZOMBIE_HEALTH);
  21.         getAttributeInstance(GenericAttributes.MOVEMENT_SPEED).setValue(movementSpeed);
  22.         getAttributeInstance(GenericAttributes.FOLLOW_RANGE).setValue(Config.DOOMSDAY_ZOMBIE_FOLLOWRANGE);
  23.         getAttributeInstance(GenericAttributes.ATTACK_DAMAGE).setValue(Config.DOOMSDAY_ZOMBIE_DAMAGE);
  24.     }

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

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

  31.     public ZombieAction getAction() {
  32.         return action;
  33.     }

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

  37.     public void ifStop() {
  38.         if (stopCount == 0) {
  39.             last_X = locX;
  40.             last_Z = locZ;
  41.         }
  42.         stopCount++;
  43.         if (stopCount == 60) {
  44.             stopCount = 0;
  45.             if (getXZDistance(last_X, last_Z, locX, locZ) < 0.5 && action == ZombieAction.Avaiable) {
  46.                 stop();
  47.             } else {
  48.                 avaiable();
  49.             }
  50.         }
  51.     }

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

  58.     public void avaiable() {
  59.         action = ZombieAction.Avaiable;
  60.         goalSelector = new PathfinderGoalSelector((world != null) && (world.methodProfiler != null) ? world.methodProfiler : null);
  61.         goalSelector.a(0, new PathfinderGoalFloat(this));
  62.         goalSelector.a(1, new PathfinderGoalZombieAttack(this, 1.0D, false));
  63.         goalSelector.a(1, new DoomsdayZombieBreakPathfinderGoal(this));
  64.         goalSelector.a(1, new DoomsdayZombiePlacePathfinderGoal(this));
  65.         targetSelector = new PathfinderGoalSelector((world != null) && (world.methodProfiler != null) ? world.methodProfiler : null);
  66.         targetSelector.a(2, new PathfinderGoalNearestAttackableTarget(this, EntityHuman.class, true));
  67.         if (world.spigotConfig.zombieAggressiveTowardsVillager) {
  68.             targetSelector.a(3, new PathfinderGoalNearestAttackableTarget(this, EntityVillager.class, false));
  69.         }

  70.     }

  71.     @Override
  72.     public void B_() {
  73.         if (hasTarget()) {
  74.             ifStop();
  75.             if (!isBlockPassable(taskHandle.getHeadBlock().getRelative(BlockFace.DOWN))) {
  76.                 taskHandle.push(new BlockTask(taskHandle.getHeadBlock().getRelative(BlockFace.DOWN)));
  77.             }
  78.             if (!isBlockPassable(taskHandle.getHeadBlock())) {
  79.                 taskHandle.push(new BlockTask(taskHandle.getHeadBlock()));
  80.             }
  81.             if (getTarget().getLocation().getY() - locY > 0.5 && (action == ZombieAction.Stop || getXZDistance(getTarget().getLocation(), this.getBukkitEntity().getLocation()) < 7)) {
  82.                 stop();
  83.                 Location loc = getLocation();
  84.                 setPosition(loc.getBlockX() + 0.5, locY, loc.getBlockZ() + 0.5);
  85.                 if (!isBlockPassable(taskHandle.getBlockOnHead())) {
  86.                     taskHandle.push(new BlockTask(taskHandle.getBlockOnHead()));
  87.                 } else {
  88.                     BlockTask task = new BlockTask(loc, 1);
  89.                     task.isUp = true;
  90.                     taskHandle.push(task);
  91.                 }
  92.             } else {
  93.                 if (locY - getTarget().getLocation().getY() > 1 && getXZDistance(bukkitEntity.getLocation(), getTarget().getLocation()) < 5 && isInWater()) {
  94.                     Location loc = getLocation().subtract(0, 1, 0);
  95.                     taskHandle.push(new BlockTask(loc.getBlock()));
  96.                     motY = -movementSpeed;
  97.                     avaiable();
  98.                 } else if (locY - getTarget().getLocation().getY() > 1 && getXZDistance(bukkitEntity.getLocation(), getTarget().getLocation()) < 0.3) {
  99.                     Location loc = getLocation().subtract(0, 1, 0);
  100.                     taskHandle.push(new BlockTask(loc.getBlock()));
  101.                     avaiable();
  102.                 } else if (isSameHeightWithTarget() || getTarget().getLocation().getY() - locY > 1 && action == ZombieAction.Stop) {
  103.                     avaiable();
  104.                 }
  105.             }
  106.         } else {
  107.             avaiable();
  108.             foundTarget();
  109.         }
  110.         taskHandle.doTick();
  111.         super.B_();
  112.     }

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

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

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

  122.     public void foundTarget() {
  123.         if (!hasTarget()) {
  124.             for (org.bukkit.entity.Entity en : bukkitEntity.getNearbyEntities(Config.DOOMSDAY_ZOMBIE_FOLLOWRANGE, Config.DOOMSDAY_ZOMBIE_FOLLOWRANGE, Config.DOOMSDAY_ZOMBIE_FOLLOWRANGE)) {
  125.                 if (en instanceof org.bukkit.entity.LivingEntity) {
  126.                     if (en instanceof org.bukkit.entity.Player) {
  127.                         if (((org.bukkit.entity.Player) en).getGameMode() != GameMode.CREATIVE) {
  128.                             setTarget((LivingEntity) en);
  129.                             return;
  130.                         }
  131.                     }
  132.                     if (en instanceof org.bukkit.entity.Villager || en instanceof org.bukkit.entity.IronGolem) {
  133.                         setTarget((LivingEntity) en);
  134.                         return;
  135.                     }
  136.                 }
  137.             }
  138.         }
  139.     }

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

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

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

  151.     public boolean hasTarget() {
  152.         if (((org.bukkit.entity.Zombie) getBukkitEntity()).getTarget() != null) {
  153.             if (!((org.bukkit.entity.Zombie) getBukkitEntity()).getTarget().isDead() && isSameWorldWithTarget()) {
  154.                 return true;
  155.             }
  156.         }
  157.         return false;
  158.     }

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

  162.     @Override
  163.     public void n() {
  164.         goalSelector.a(0, new PathfinderGoalFloat(this));
  165.         goalSelector.a(1, new PathfinderGoalZombieAttack(this, 1.0D, false));
  166.         targetSelector.a(2, new PathfinderGoalNearestAttackableTarget(this, EntityHuman.class, true));
  167.         if (world.spigotConfig.zombieAggressiveTowardsVillager) {
  168.             targetSelector.a(3, new PathfinderGoalNearestAttackableTarget(this, EntityVillager.class, false));
  169.         }
  170.         goalSelector.a(1, new DoomsdayZombieBreakPathfinderGoal(this));
  171.         goalSelector.a(1, new DoomsdayZombiePlacePathfinderGoal(this));
  172.     }

  173.     public enum ZombieAction {
  174.         Avaiable,
  175.         Stop;
  176.     }
  177. }
复制代码




尘晓凡
https://www.mcbbs.net/thread-811096-1-1.html
请观看 自定义生物的教程
如果对有生命的实体进行开发
需要注册实体 否则就会看不见
1.11为分界线 注册方法不同
[img]%5Burl=https://sm.ms/image/642kJDQAVemgYwN%5D[/url][/img]
以上代码均来自教程
详情可前往观看

谢谢你了
凉拌凑字凑字还好还好

TopLuren
正好是我需要的,太感谢了