Помогите Шкала жажды и кислорода

fx8320e

Активный участник
Пользователь
Баллы
66
Приветствую! Взялся за написание плагина, привносящего в игру систему жажды. Тема избитая, но в моих планах использовать для отображения уровня жажды стандартную шкалу воздуха, а кислород же переложить на bossbar. Собственно, вопросы:
1) Как сделать шкалу воздуха видимой не только в воде?
2) Как убавлять значение шкалы с течением времени?
3) Как убрать механику убавление шкалы воздуха в воде?*
* Пока есть такой костыльный вариант, однако, он работает только прим перемещении игрока. То есть, если игрок стоит на месте, кислород перестает восполняться.
PHP:
 @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = false)
        public void waterair(PlayerMoveEvent p) {
         
        Player e = p.getPlayer();
        int x = (int) e.getLocation().getX();
        int y = (int) e.getLocation().getY();
        int z = (int) e.getLocation().getZ(); 
       
        if (e.getWorld().getBlockAt(x, y+1, z).getType().equals(Material.WATER) && e.getRemainingAir() < 300) {
            int a = e.getRemainingAir();
            e.setRemainingAir(a+20);       
    }
    }
Если знаете решение, подскажите, пожалуйста. Заранее благодарю!
 
1) Как сделать шкалу воздуха видимой не только в воде?
Скорее всего достаточно держать уровень воздуха на player.getMaximumAir() - 1 через EntityAirChangeEvent, но неуверен, пытается ли клиент сам восстановить воздух. Если да - возможно, стоит установить максимальное количество воздуха на какое-то большое значение и разницу оставить побольше, если воздухом все равно собираешься управлять сам.
2) Как убавлять значение шкалы с течением времени?
3) Как убрать механику убавление шкалы воздуха в воде?
Опять же EntityAirChangeEvent.
 
Скорее всего достаточно держать уровень воздуха на player.getMaximumAir() - 1 через EntityAirChangeEvent, но неуверен, пытается ли клиент сам восстановить воздух. Если да - возможно, стоит установить максимальное количество воздуха на какое-то большое значение и разницу оставить побольше, если воздухом все равно собираешься управлять сам.

Опять же EntityAirChangeEvent.
Спасибо! Но не могли бы вы подробней расписать. Не вижу никаких функций EntityAirChangeEven, которые могли бы мне помочь.
 
Спасибо! Но не могли бы вы подробней расписать. Не вижу никаких функций EntityAirChangeEven, которые могли бы мне помочь.
Достаточно слушать событие и исправлять его поведение как то требуется. Событие в любом случае будет производиться, если игрок в воде, или же вышел на воздух. Если player.getRemainAir() < event.getAmount(), значит игрок вышел на воздух; если наоборот, значит он в воде. В зависимости от ситуации нужно устанавливать event.setAmount(int). Также стоит запустить шедулер, который будет раз в несколько секунд проверять, чтоб значение player.getRemainAir() всегда было меньше player.getMaximumAir() - на случай первого входа, смерти, или чего непредвиденного.
 
Достаточно слушать событие и исправлять его поведение как то требуется. Событие в любом случае будет производиться, если игрок в воде, или же вышел на воздух. Если player.getRemainAir() < event.getAmount(), значит игрок вышел на воздух; если наоборот, значит он в воде. В зависимости от ситуации нужно устанавливать event.setAmount(int). Также стоит запустить шедулер, который будет раз в несколько секунд проверять, чтоб значение player.getRemainAir() всегда было меньше player.getMaximumAir() - на случай первого входа, смерти, или чего непредвиденного.
Как мне кажется для чистоты измерения следует проверять среду в которой находится игрок не расходом воздуха (ведь он будет убавляться и на суше, если мы переделаем его под жажду), а проверять блок, в котором находится голова игрока, и если это вода, то что-то делать. Выше я привел вариант, но он работает исключительно при движении игрока, в чем собственно и проблема. Потому, если вас не затруднит, расскажите в чем проблема данного подхода. И еще раз, как сделать шкалу воздуха видимой не только в воде?
 
Как мне кажется для чистоты измерения следует проверять среду в которой находится игрок не расходом воздуха (ведь он будет убавляться и на суше, если мы переделаем его под жажду), а проверять блок, в котором находится голова игрока, и если это вода, то что-то делать. Выше я привел вариант, но он работает исключительно при движении игрока, в чем собственно и проблема. Потому, если вас не затруднит, расскажите в чем проблема данного подхода. И еще раз, как сделать шкалу воздуха видимой не только в воде?
c while вместо if в этой строчке if (e.getWorld().getBlockAt(x, y+1, z).getType().equals(Material.WATER) && e.getRemainingAir() < 300) происходит то же самое...
 
Как мне кажется для чистоты измерения следует проверять среду в которой находится игрок не расходом воздуха (ведь он будет убавляться и на суше, если мы переделаем его под жажду), а проверять блок, в котором находится голова игрока, и если это вода, то что-то делать. Выше я привел вариант, но он работает исключительно при движении игрока, в чем собственно и проблема. Потому, если вас не затруднит, расскажите в чем проблема данного подхода. И еще раз, как сделать шкалу воздуха видимой не только в воде?
Если хочется получить полный контроль - тогда событие следует отменять в принципе - таким боком изменяться оно без твоего воздействия не будет.
Далее через шедулер проверять проверять, находится ли голова в воде. Опять же, чтобы пузырьки не пропадали, следует держать уровень кислорода несколько меньше, чем максимальное количество.
Код:
private static final int TICKS_PER_CHECK = 5; // Как часто проверять игроков?

Bukkit.getScheduler().runTaskTimer(plugin, () -> {
    for (Player player : Bukkit.getOnlinePlayers()) {
        Material type = player.getEyeLocation().getBlock().getType();
        if (type == Material.WATER) {
            int newAir = Math.min(player.getRemainingAir() + TICKS_PER_CHECK, player.getMaximumAir() - 80); // Если игрок в воде, добавить TICKS_PER_CHECK воздуха, вплоть до (максимум_игрока - 80)
            player.setRemainingAir(newAir);
        } else if (player.getRemainingAir() > 0) {
            int newAir = Math.max(player.getRemainingAir() - TICKS_PER_CHECK, 0); // Если игрок не в воде, забрать TICKS_PER_CHECK воздуха, вплоть до 0
            player.setRemainingAir(newAir);
        }
    }
}, TICKS_PER_CHECK, TICKS_PER_CHECK);
 
Назад
Верх