Помогите Создание NPC

HaloSpartan

Активный участник
Пользователь
Баллы
66
Привет форумчане!
Мне нужна помощь по поводу создания NPC(игрок), как можно это сделать?
Подскажите как это можно сделать, да и так чтобы с ним можно было взаимодействовать(допустим ПКМ).
По форумам лазил, не нашёл нужной ин-фы.
Заранее благодарю
 
Понадобится ProtocolLib(либо ползать в nms). Ставишь моба, который в последствии будет твоим НИПом. Ловишь пакет с этим мобом, посылаешь редактированный с тем же entity-id, профит. На словах то просто, но если не работал с этим никогда - придется помучаться.
А можно не париться и использовать Lib's Disguises с его API, и все скатывается до DisguiseAPI.disguiseToAll(твойМоб, new PlayerDisguise("Пример"))
Готовое решение - Citizens, но каждый раз, когда я сам ставил этот плагин на сервер, он начинал лагать. Впрочем, это было 5 лет назад, и наверняка всё переменилось.
 
Обновлено:
Создал отдельную тему с актуальной информацией по созданию NPC в игре: https://rubukkit.org/threads/190265

Citizens - самый простой способ вообще, если достаточно стоящих на месте моделек, по которым нужно отслеживать нажатия.

Если модельки должны рандомно передвигаться по местности - то спаунить, например, жителей и менять им тип на игроков при помощи LibsDisguises. Пробовал ещё iDisguise, но он более багованый и с меньшим количеством возможностей.

Если нужен кастомный интеллект - то тут:
1) Либо Citizens, где нужно полностью самому реализовывать интеллект при помощи Bukkit
2) Либо BKCommonLib, где вроде как готовые блоки интеллекта (как в самой игре). Но это не точно - сам не использовал
3) Либо NMS + рефлексия. Придётся использовать готовые блоки интеллекта или реализовывать свои goalSelector'ы и targetSelector'ы

Впрочем, это было 5 лет назад, и наверняка всё переменилось.
Сейчас всё в порядке, да.
 
Последнее редактирование:
Привет форумчане!
Мне нужна помощь по поводу создания NPC(игрок), как можно это сделать?
Подскажите как это можно сделать, да и так чтобы с ним можно было взаимодействовать(допустим ПКМ).
По форумам лазил, не нашёл нужной ин-фы.
Заранее благодарю
Код:
{
          Location loc = new Location(Bukkit.getWorld("world"), 99.5, 87, 97.5, 1, 0);
            Villager king = (Villager)loc.getWorld().spawnEntity(loc, EntityType.VILLAGER);
            king.addPotionEffect(new PotionEffect(PotionEffectType.SLOW, 999999999, 10, true, false));
            king.addPotionEffect(new PotionEffect(PotionEffectType.DAMAGE_RESISTANCE, 999999999, 5, true, false));
            king.setCustomNameVisible(true);
            king.setCustomName("§bКороль");
            king.setCollidable(false);
            king.setAI(false);
            king.resetMaxHealth();
        }

  @EventHandler
  public void onPlayerInteractEntity(PlayerInteractEntityEvent e)
  {
    if (!(e.getRightClicked() instanceof Villager)) return;
    Entity ent = e.getRightClicked();
    if ((ent instanceof Villager)) {
      Player p = e.getPlayer();
      if(ent.getCustomName() == null)return;
      if (ent.getCustomName().equalsIgnoreCase("§bКороль"))
      {
        e.setCancelled(true);
        p.sendMessage("Здравствуй HaloSpartan");
    }
   }
}
 
Код:
{
          Location loc = new Location(Bukkit.getWorld("world"), 99.5, 87, 97.5, 1, 0);
            Villager king = (Villager)loc.getWorld().spawnEntity(loc, EntityType.VILLAGER);
            king.addPotionEffect(new PotionEffect(PotionEffectType.SLOW, 999999999, 10, true, false));
            king.addPotionEffect(new PotionEffect(PotionEffectType.DAMAGE_RESISTANCE, 999999999, 5, true, false));
            king.setCustomNameVisible(true);
            king.setCustomName("§bКороль");
            king.setCollidable(false);
            king.setAI(false);
            king.resetMaxHealth();
        }

  @EventHandler
  public void onPlayerInteractEntity(PlayerInteractEntityEvent e)
  {
    if (!(e.getRightClicked() instanceof Villager)) return;
    Entity ent = e.getRightClicked();
    if ((ent instanceof Villager)) {
      Player p = e.getPlayer();
      if(ent.getCustomName() == null)return;
      if (ent.getCustomName().equalsIgnoreCase("§bКороль"))
      {
        e.setCancelled(true);
        p.sendMessage("Здравствуй HaloSpartan");
    }
   }
}
Человеку нужна модельная игрока, а не житель.
Думаю, жителя он и сам умеет спаунить.
Да и по имени проверять нажатие по мобу - такое себе
 
Citizens - самый простой способ вообще, если достаточно стоящих на месте моделек, по которым нужно отслеживать нажатия.

Если модельки должны рандомно передвигаться по местности - то спаунить, например, жителей и менять им тип на игроков при помощи LibsDisguises. Пробовал ещё iDisguise, но он более багованый и с меньшим количеством возможностей.

Если нужен кастомный интеллект - то тут:
1) Либо Citizens, где нужно полностью самому реализовывать интеллект при помощи Bukkit
2) Либо BKCommonLib, где вроде как готовые блоки интеллекта (как в самой игре). Но это не точно - сам не использовал
3) Либо NMS + рефлексия. Придётся использовать готовые блоки интеллекта или реализовывать свои goalSelector'ы и targetSelector'ы


Сейчас всё в порядке, да.
Сможешь просветить по 3-ему пункту? Хотелось бы узнать как всё самому сделать
 
Обновлено:
Создал отдельную тему с актуальной информацией по созданию NPC в игре: https://rubukkit.org/threads/190265

Сможешь просветить по 3-ему пункту? Хотелось бы узнать как всё самому сделать
Сложно тебе будет начинать сразу с NMS. Обычно новички начинают как раз с изучения библиотек. Если функционала недостаточно - уже лезут в НМС.
Более того, при использовании NMS тебе придётся вручную переписывать код под каждую новую версию игры.


Если так хочешь NMS - разберись сначала со статическими NPC из видоса выше.
Если не получается - конкретизируй, в чём именно проблема.


Ну а дальше... Пристёгивай ремни, мы отправляемся в ад.

Берём в зубы IDEA со встроенным fernflower и идём декомпилировать классы ядра и смотреть, как реализован тот или иной моб.
Названия классов энтити в NMS имеют вид "EntityМоб". Например, EntitySpider.
Для примера копируем содержимое класса и переделываем под себя.

Например вот так:
PHP:
import net.minecraft.server.v1_some.*;

public class CustomSpider extends EntitySpider {
    protected CustomSpider(World world) {
        super(world);
    }

    @Override
    protected void n() {
        this.goalSelector.a(1, new PathfinderGoalFloat(this));
        this.goalSelector.a(3, new PathfinderGoalLeapAtTarget(this, 0.4F));
        this.goalSelector.a(4, new PathfinderGoalSpiderMeleeAttack(this));
        this.goalSelector.a(5, new PathfinderGoalRandomStrollLand(this, 0.8D));
        this.goalSelector.a(6, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 8.0F));
        this.goalSelector.a(6, new PathfinderGoalRandomLookaround(this));
        this.targetSelector.a(1, new PathfinderGoalHurtByTarget(this, false));
        this.targetSelector.a(2, new PathfinderGoalNearestAttackableTarget<>(this, EntityPlayer.class, true));
    }

    static class PathfinderGoalSpiderMeleeAttack extends PathfinderGoalMeleeAttack {
        PathfinderGoalSpiderMeleeAttack(EntityCreature creature) {
            super(creature, 1.0D, true);
        }

        public boolean b() { //needNavigatePath
            float f = this.a.az();
            if (f >= 0.5F && this.a.getRandom().nextInt(100) == 0) {
                this.a.setGoalTarget(null);
                return false;
            } else {
                return super.b();
            }
        }

        protected double a(EntityLiving entityliving) {
            return (double) (4.0F + entityliving.width);
        }
    }
}

Можешь заходить в различные классы блоков ИИ (например, PathfinderGoalRandomLookaround) и смотреть, как они работают. При аналогии можешь делать свои.

Как теперь заспаунить энтити, который будет работать при помощи нашего класса?

Есть два пути - "вручную" и рефлексией.
Первый вариант работает быстрее, второй более красивый + универсальный + с потенциалом поддержки мультиверсионности.

В обоих случаях нам понадобится следующий метод:
PHP:
    private org.bukkit.entity.Entity initNmsEntity(Entity nmsEntity, Location location) {
        nmsEntity.setLocation(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch());
        nmsEntity.setPositionRotation(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch());
        ((CraftWorld) location.getWorld()).getHandle().addEntity(nmsEntity, CreatureSpawnEvent.SpawnReason.CUSTOM);
        return nmsEntity.getBukkitEntity();
    }


Вручную будет примерно так так:
PHP:
    public org.bukkit.entity.Entity spawnNmsEntity(EntityType bukkitType, Location location) {
        WorldServer nmsWorld = ((CraftWorld) location.getWorld()).getHandle();
        switch (bukkitType) {
            case SPIDER:
                return this.initNmsEntity(new NmsAggressiveSpider(nmsWorld), location);
            default:
                throw new IllegalArgumentException("Неподдерживаемый тип энтити");
        }
    }


Рефлексией будет примерно так:
PHP:
    private Map<Class<? extends org.bukkit.entity.Entity>, Constructor<? extends Entity>> nmsConstructors = new HashMap<>();

    private void registerNmsEntity(Class<? extends org.bukkit.entity.Entity> bukkitClass, Class<? extends Entity> clazz) throws NoSuchMethodException {
        Constructor<? extends Entity> constructor = clazz.getDeclaredConstructor(World.class);
        constructor.setAccessible(true);
        this.nmsConstructors.put(bukkitClass, constructor);
    }

Сам процесс регистрации (нужно будет вызывать один раз при запуске сервера):
this.registerNmsEntity(Spider.class, CustomSpider.class);
На самом деле, кэшировать конструкторы можно по мере необходимости - тут кому как нравится, разницы особо нет.

PHP:
    private org.bukkit.entity.Entity spawnNmsEntity(Class<? extends org.bukkit.entity.Entity> bukkitClass, Location location) {
        try {
            WorldServer nmsWorld = ((CraftWorld) location.getWorld()).getHandle();
            Entity nmsEntity = this.nmsConstructors.get(bukkitClass).newInstance(nmsWorld);
            return this.initNmsEntity(nmsEntity);
        } catch (Exception e) {
            throw new RuntimeException("Не удалось заспаунить энтити", e);
        }
    }


P.S. Есть для тебя одно предложение. Если интересно - черкани в ЛС на форуме или по одному из контактов на Dymeth.ru
 
Последнее редактирование:
2) Либо BKCommonLib, где вроде как готовые блоки интеллекта (как в самой игре). Но это не точно - сам не использовал
Да там есть готовый интелект копипаст с ванилы, в котором еще и свое можно внедрить.
 
Назад
Верх