生成带有自定义骑手的自定义马匹

Spawn a custom horse with a custom rider

我想生成一匹自定义马和它的自定义骑手生物,然后自定义它们。但是,一旦调用 spawn(loc, Horse.class),就无法在它生成之前调用 getEntity()。 您也不能从 spawn(loc, custommob); 之类的变量或任何预先定制的实体中生成生物。而且你不能实例化一个 new Horse();.

所以这匹马需要在没有任何定制、没有骑手的情况下生成,然后才能修改。但这将触发一个 EntitySpawnEvent 将被取消,因为 'default horses' 在我的世界中不允许生成。并且没有自定义我可以给它以供以后识别它并使其通过取消。

我的骑手也有同样的问题,在它生成之前我无法自定义它,因此在它生成后我无法将它识别为骑手。 如果我生成任何在生成黑名单上的东西,它就会被取消,如果我在白名单上生成任何东西,它只会生成并且无法识别。我不希望任何现存的随机暴民突然成为骑手。

如何在遵守黑名单的情况下生成这两个生物,自定义它们,并让它们相互找到对方并成为彼此的乘客?

@EventHandler
public void onMobSpawn(CreatureSpawnEvent event) {
    String world = event.getEntity().getWorld().getName();
    if (world.equals("Someworld") || world.equals("Someotherworld")) {
        if (event.getEntityType().equals(EntityType.SKELETON)) { // Whitelisted
            // Continue whitelist actions
        }
    } else {
        /* I could add here to spawn the horse, and add an exception to the filter.
         * But how do I customize it?
         * I can't customize it before it spawned and I can't get it after it spawned.
         * Same for the rider.
         */
        // loc.getWorld().spawn(loc, Horse.class);
        event.setCancelled(true);
    }
}

马在生成后实际上是可以得到的。当调用 world.spawnEntity(Location, EntityType) 时,它 returns 生成了实体。

因此,要在一匹马生成后得到它,您可以使用:

Entity entity = location.getWorld().spawnEntity(location, EntityType.HORSE);
Horse horse = (Horse) entity

一旦你拥有了这匹马,你可以按照你喜欢的方式自定义它,例如:

horse.setCustomName("My Custom Horse");

horse.setPassenger(horseRider);

您也可以为您喜欢的任何其他实体执行此操作。因此,您的代码可能如下所示:

Horse horse = (Horse) location.getWorld().spawnEntity(location, EntityType.HORSE);
Skeleton rider = (Skeleton) location.getWorld().spawnEntity(location, EntityType.SKELETON);
//customize the rider and horse in any way you want

horse.setPassenger(rider);

如果您要在 CreatureSpawnEvent 或其他类似的生成事件中调用此代码,请确保:

!event.getSpawnReason().equals(SpawnReason.CUSTOM)

再次生成实体之前,避免无限循环

尽管生成和自定义实体之间应该几乎没有延迟,但如果需要,您可以将它们生成在一个单独的位置(例如生成世界或其他地方),然后在设置之前将它们传送到正确的位置乘客:

horse.teleport(realLocation);
skeleton.teleport(realLocation);

horse.setPassenger(skeleton);

不过,这应该不是必需的,除非您正在异步进行自定义,这不应该首先通过设置实体信息来完成。

CreatureSpawnEvent.getSpawnReason() 是您问题的一个很好的解决方法。 看看SpawnReason.CUSTOM.

When a creature is spawned by plugins

@EventHandler
public void onNormal(CreatureSpawnEvent event) {
    // This will prevent an infinite loop
    if (event.getSpawnReason() != SpawnReason.CUSTOM) {
        event.setCancelled(true);
        // Spawn what you want
    }
}