- Поддерживаемые версии
- 1.16
Гайд по существам - мобам, специальным существам и прочим.
Туториалы: 1) Bukkit API - написание плагинов 2) Bukkit API - написание плагинов, эвенты и команды 3) Bukkit API - Сущности |
Гайд писался с использованием последней версии игры - 1.16.3, но тем не менее, все это может (и должно) работать как на более старых, так и на более новых версиях.
В игре присутствует много сущностей. Скелет, кошка, файрболл, лежащий предмет, стрела или летящий пузырек опыта - это все сущности. Каждая сущность в игре так или иначе является наследником класса Entity, независимо от того, является ли она живым существом или каким-то предметом.
В Bukkit API все существа представлены в виде интерфейса Entity. Он содержит все базовые методы, одинаковые для всех сущностей в игре, например, Entity#getEntityId() который вернет ID существа. Однако, существа имеют свои интерфейсы: для жителя интерфейс будет Villager, для игрока - Player. Эти интерфейсы помимо методов интерфейса Entity имеют свои уникальные методы - Player#chat(String msg) отправляет сообщение в чат от имени игрока. Однако, этого метода нет у родительского интерфейса Entity или у интерфейса Villager, потому что писать в чат могут только игроки.
Все интерфейсы существ можно посмотреть вот тут.
Каждое существо имеет так же свой EntityType. Это нужно для удобного разделения мобов на виды друг от друга.
Опираясь на документацию, приступим к практике.
Сделаем кость, которая будет спавнить рядом с игроком сильного волка - словно мы Рексар из Warcraft.
Начну с того, что мы не можем создать существо с помощью конструктора
Entity e = new Entity();
, поскольку Entity является интерфейсом, для которого нужна реализация. Вместо этого мы можемиспользовать метод World#spawnEntity(Location loc, EntityType type) из интерфейса World. Поскольку метод возвращает ссылку на заспавненное существо, мы можем производить с ним разные действия.
Java:
// спавнит волка на локации location
// получать ссылку на существо не обязательно, но мы ведь хотим работать с ним в дальнейшем
Wolf wolf = (Wolf) world.spawnEntity(location, EntityType.WOLF);
И так, теперь мы знаем как спавнить существо. Сделаем обработчик события взаимодействия игрока с миром:
Java:
@EventHandler
public void onPlayerInteract(PlayerInteractEvent event) {
}
Теперь создадим где-нибудь в этом же классе метод для спавна нашего волка:
Java:
/**
* Спавн прирученного, более сильного волка
*
* @param owner - игрок-владелец волка
* @param location - локация, на которой будет заспавнен волк
* @return объект прирученного волка
*/
private Wolf spawnTamedWolf(Player owner, Location location) {
World world = location.getWorld();
// создаем нашего волка
// поскольку метод World#spawnEntity() возвращает Entity, а не Wolf,
// мы должны выполнить приведение типов
Wolf wolf = (Wolf) world.spawnEntity(location, EntityType.WOLF);
// устанавливаем владельца волка
wolf.setOwner(owner);
wolf.setTamed(true);
// устанавливаем характеристики волка: имя и здоровье
wolf.setCustomName("§c[§7Волк§c] " + owner.getName());
// поскольку метод Entity#setMaxHealth() помечен как устаревший,
// мы обращаемся к атрибуту "generic.max_health" и устанавливаем его
// значение на 50.0 единиц (25 сердечек)
wolf.getAttribute(Attribute.GENERIC_MAX_HEALTH).setBaseValue(50.0D);
return wolf;
}
Конечно, мы могли написать все это прямо в обработчике, после выполнения нужных нам условий, но вынесение кода в отдельные методы может повысить его читаемость.
Вернемся к обработчику событий. Нам нужно проверить, есть ли у игрока в руках кость, и именно та кость, которая нам нужна, затем создать волка-помощника.
Java:
@EventHandler
public void onPlayerInteract(PlayerInteractEvent event) {
// получаем ссылку на игрока из события
Player player = event.getPlayer();
// получаем ссылку на кликнутый блок
Block clicked = event.getClickedBlock();
// если блок воздух - пропускаем выполнение дальнейшего кода
if (clicked.isEmpty() || clicked.getType().isAir())
return;
// получаем ссылку на предмет в главной руке
ItemStack stack = player.getInventory().getItemInMainHand();
// проверяем, является ли предмет костью
if (stack.getType() == Material.BONE) {
// проверяем, имеет ли предмет ItemMeta
// если у предмета не будет ItemMeta, но мы захотим получить имя предмета,
// сервер выбросит NullPointerException
if (stack.hasItemMeta()) {
ItemMeta meta = stack.getItemMeta();
// желательно сделать проверку, имеет ли предмет имя
// заодно мы проверяем имя предмета
if (meta.hasDisplayName()
&& meta.getDisplayName().equalsIgnoreCase("§eШаманская кость")) {
spawnTamedWolf(player, clicked.getLocation());
player.sendMessage("§eВаш волк призван. Пора на охоту!");
}
}
}
}
Что получилось? Если игрок возьмет в руку кость с названием "§eШаманская кость" и нажмет правой кнопкой по блоку, он получит своего личного волка с большим количеством здоровья. Волку можно изменить количество урона, выдать эффекты зелья, или вообще посадить на него игрока - все завит от фантазии. Это можно сделать с помощью методов из документации. Вот ссылка на документацию к волку.
Мы могли добавить больше условий, например, чтобы при использовании кости у игрока снимался опыт и накладывалась задержка, но гайд был не об этом. Если что-то не понятно или объяснено плохо, напишите в обсуждения ресурса.