Помогите Задержка на использование жемчуга и плодов хоруса

Статус
Закрыто для дальнейших ответов.

WhileInside

Активный участник
Пользователь
Баллы
66
Имя в Minecraft
WhileInside
Как можно сделать задержку на жемчуг эндера и плодов хоруса при определённом условии?

Сделал вот такой метод

Код:
    private void useItem(ItemStack item, Player player) {
        if (item.getType() != Material.CHORUS_FRUIT && item.getType() != Material.ENDER_PEARL) {
            return;
        }

        //if (!combatManager.isFighting(player)) {
        //    return;
        //}

        player.setCooldown(item.getType(), 15 * 20);
    }

Вызываю его во время PlayerLaunchProjectileEvent и PlayerItemConsumeEvent, вроде бы .setCooldown вызывается (выводил сообщение в чат), но никакое кд не ставиться.

P.S Делать тасками или в мапе хранить время не особо хочется, но если не будет других вариантов, то похоже придётся.
 
У меня никогда не возникало проблем с этим методом. Какая версия сервера и ядро?
 
На всякий случай спрошу, у тебя установка cd в основном потоке выполняется? Никаких async не кидаешь?
Метод вызывается в двух обработчиках эвентов, эвенты вроде бы синхронные, так что да, в основном
 
С "Хорусом" можно вот так сделать, а с "Жемчугом эндера" аналогично, но будет ивент PlayerInteractEvent;

Код:
    private HashMap<String, Long> chorusItems = new HashMap<>();
    private long timeChorus = 40000;

    @EventHandler
    public void onConsumItem(PlayerItemConsumeEvent event) {
        Player player = event.getPlayer();

        if (event.getItem().getType() == Material.CHORUS_FRUIT) {
            if (cdChorus(player.getName())) {
                player.sendMessage("§7Использовал §f\"Плод хоруса\"§7.");
                return;
            }
            long message = chorusItems.get(player.getName()) - System.currentTimeMillis();
            player.sendMessage("§7У вас кд, ждите§f " + String.valueOf(message / 1000L) + " §7секунд.");
            event.setCancelled(true);
        }
    }

public boolean cdChorus(String player) {
        if (!chorusItems.keySet().contains(player) || chorusItems.get(player) < System.currentTimeMillis()) {
            chorusItems.put(player, System.currentTimeMillis() + timeChorus);
            return true;
        }
        return false;
    }
 
Последнее редактирование:
С "Хорусом" можно вот так сделать, а с "Жемчугом эндера" аналогично, но будет ивент PlayerInteractEvent;

Код:
    private HashMap<String, Long> chorusItems = new HashMap<>();
    private long timeChorus = 40000;

    @EventHandler
    public void onConsumItem(PlayerItemConsumeEvent event) {
        Player player = event.getPlayer();

        if (event.getItem().getType() == Material.CHORUS_FRUIT) {
            if (cdChorus(player.getName())) {
                player.sendMessage("§7Использовал §f\"Плод хоруса\"§7.");
                return;
            }
            long message = chorusItems.get(player.getName()) - System.currentTimeMillis();
            player.sendMessage("§7У вас кд, ждите§f " + String.valueOf(message / 1000L) + " §7секунд.");
            event.setCancelled(true);
        }
    }

public boolean cdChorus(String player) {
        if (!chorusItems.keySet().contains(player) || chorusItems.get(player) < System.currentTimeMillis()) {
            chorusItems.put(player, System.currentTimeMillis() + timeChorus);
            return true;
        }
        return false;
    }
Смотри постскриптум:
Делать тасками или в мапе хранить время не особо хочется

Ладно, я так понял, Bukkit почему-то не хочет ставить кд

Я уже сделал мапой, так что всем спасибо, вот примерно такой код получился:

Код:
    private final TObjectLongMap<Player> cooldowns
            = new TObjectLongHashMap<>();

    @EventHandler(priority = LOWEST)
    public void onQuit(PlayerQuitEvent event) {
        cooldowns.remove(event.getPlayer());
    }

    @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
    public void onProjectile(PlayerLaunchProjectileEvent event) {
        boolean result = useItem(event.getItemStack(), event.getPlayer());

        if (result) {
            event.setCancelled(true);
        }
    }

    @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
    public void onConsume(PlayerItemConsumeEvent event) {
        boolean result = useItem(event.getItem(), event.getPlayer());

        if (result) {
            event.setCancelled(true);
        }
    }

    private boolean useItem(ItemStack item, Player player) {
        if (item.getType() != Material.CHORUS_FRUIT && item.getType() != Material.ENDER_PEARL) {
            return false;
        }

        long now = System.currentTimeMillis();
        long usageAvailableAt = cooldowns.get(player);

        if (now < usageAvailableAt) {
            // todo send message
            return true;
        }

        if (!combatManager.isFighting(player)) {
            return false;
        }

        cooldowns.put(player, now + 15_000);

        return false;
    }
 
Статус
Закрыто для дальнейших ответов.
Назад
Верх