Войти или зарегистрироваться
  • Вы находитесь в сообществе Rubukkit. Мы - администраторы серверов Minecraft, разрабатываем собственные плагины и переводим на различные языки плагины наших коллег из других стран.

Помогите Bukkit.getPluginManager().registerEvent()

Andrine

Активный участник
Пользователь
Баллы
66
Здравствуйте уважаемые жители этого форума:confused:, во время разработки плагинов, я столкнулся с 3-мя вопросами.

1) А собственно, Bukkit это класс, getPluginManager() - метод, но как метод, может иметь еще один метод при себе? Разве поле может иметь такие скобки ()?

2) При регистрации, я создаю экземпляр класса new Handler(). Для каждого игрока, создается свой Handler, или он создается для всех один, при запуске сервера, а евенты вызываются в этом созданном, но для каждого свои?

3) Вытекает из 2-го, есть плагин на респавн. После смерти, игрок должен подождать 5 секунд, чтобы возрадиться, но у донатера уменьшена эта задержка. У меня есть класс Handler, его поле delay, сразу равно 5-ти. В смертельном евенте, я проверяю, если игрок донатер delay = delay - 3; Если нет, ничего. Потом запускаю шедулер, где указываю время респавна в delay. И еще шедулер, который каждые 20-ть тиков оповещает, сколько осталость до возраждения, но из-за багов, я начал подозревать, что если 2-игрока умерли, то delay донатера, может перебить делай игрока, и у игрока станет delay 2. Тоесть, я подозреваю, что delay меняется на тот, который я указал последним, и даже в запущенном шедулере, берется именно последний указаный.
Вот код для наглядности:

Код:
short delay = 5;

@EventHandler
public void onDeath(PlayerDeathEvent event) {
    if(player.permission("vip")) delay = delay - 2;
    runScheduler.ScheduleSyncDelayedTask( ->  bla bla, delay)
    runScheduler.ScheduleSyncRepeatingTask( ->  {
message(вам осталось до репса delay);

delay = delay - 1;
}, delay, delay)
}

Код писал здесь, если не понятна суть вопроса, постараюсь обьяснить иначе.
 
1. getPluginManager() возвращает класс PluginManager в котором есть свои методы

2. Handler'ы создаются для ивента отдельно

3. Нет, на каждого игрока вызывается отдельный PlayerDeathEvent
 
1. getPluginManager() возвращает класс PluginManager в котором есть свои методы

2. Handler'ы создаются для ивента отдельно

3. Нет, на каждого игрока вызывается отдельный PlayerDeathEvent

Отдельно? У меня есть класс Handler. В нём joinEvent. Тоесть, для каждого игрока создается отдельный класс Handler? Или он для всех один, а вот ивенты в нём уже для каждого?

С третьим вопрос из 2-го, у меня delay просто багается, будто меняется на последний перезаписанный. Это говорит что класс один, но я не доконца в этом уверен, да и вопрос, а как сделать тогда для каждого свой делай возраждения. Я помню, что это можно сделать простыми переменными, пусть даже ссылочными, но видимо, если класс один, то придется хранить время возраждения для каждого игрока в Map и сразу менять его =( Бедный мой сервер:cry:
 
Класс создастся в том количестве экземпляров, в котором, ты его создал. Если написал nеw Handler 1 раз, значит бyдет 1 класс, от игрока ничего зависеть не может. Когда происходит событие(Еvеnt) то тригирится твой метод
 
Инстанс класса Handler ты создал единственный раз. Соответственно, у тебя один общий объект на всех игроков.
И, получается, поле delay тоже общее на всех - отсюда и баги.

Помимо этого, есть ещё одна проблема - ты запускаешь, но не останавливаешь задачи шедулера (repeating task). В конечном итоге их может стать столько, что они начнут существенно нагружать процессор.

Решения проблемы с delay я вижу три:

1) Создавать для каждого игрока свой Handler. Но этот вариант не рекомендую, потому что такая практика используется крайне редко, и может ввести в заблуждение других разработчиков. Ну, и, к тому же, в будущем придется обрабатывать не только игроков, но и другие события - например, событие смены погоды в мире

2) Вместо одного числового значения хранить таблицу соответствия игроков их числам: Map<UUID, Short>
UUID - это айди игрока. Вместо UUID можно использовать объект Player..
Но в любом случае важно своевременно удалять неактуальные записи из таблицы, чтобы избежать утечки памяти.
Вариант неплохой, но в данном случае в нем практически нет смысла, потому что существует ещё более оптимальное решение

3) Вовсе отказаться от использования полей в самом классе Handler, а переменную delay создавать и использовать только внутри метода обработки события
 
Последнее редактирование:
Инстанс класса Handler ты создал единственный раз. Соответственно, у тебя один общий объект на всех игроков.
И, получается, поле delay тоже общее на всех - отсюда и баги.

Помимо этого, есть ещё одна проблема - ты запускаешь, но не останавливаешь задачи шедулера (repeating task). В конечном итоге их может стать столько, что они начнут существенно нагружать процессор.

Решения проблемы с delay я вижу три:

1) Создавать для каждого игрока свой Handler. Но этот вариант не рекомендую, потому что такая практика используется крайне редко, и может ввести в заблуждение других разработчиков. Ну, и, к тому же, в будущем придется обрабатывать не только игроков, но и другие события - например, событие смены погоды в мире

2) Вместо одного числового значения хранить таблицу соответствия игроков их числам: Map<UUID, Short>
UUID - это айди игрока. Вместо UUID можно использовать объект Player..
Но в любом случае важно своевременно удалять неактуальные записи из таблицы, чтобы избежать утечки памяти.
Вариант неплохой, но в данном случае в нем практически нет смысла, потому что существует ещё более оптимальное решение

3) Вовсе отказаться от использования полей в самом классе Handler, а переменную delay создавать и использовать только внутри метода обработки события
Так ее шедулер в таком случае не видит
 
С чего бы не увидит? Переменная внутри метода и шедулер создаётся внутри метода. В чём проблема?
так шедулер RepeatTask, значение переменной - его задержка перед повторениями. Метод выполняется и уходит в аут, а шедулер дальше пашет, откуда ей брать значение этой переменной? Тебе даже Интеллидж не даст забилдить такую парашу.
 
так шедулер RepeatTask, значение переменной - его задержка перед повторениями. Метод выполняется и уходит в аут, а шедулер дальше пашет, откуда ей брать значение этой переменной? Тебе даже Интеллидж не даст забилдить такую парашу.
Перенеси переменную внутрь метода, и ничего не изменится )
 
Перенеси переменную внутрь метода, и ничего не изменится )
А если у меня шедулер, который выполняется в репеате 5 раз, это сделано hashmap delay, я добавлю ник игрока, и значение как делай. При каждом выполнеии, добавлю делай+, и если делай > 5, то отменить таску, а где ее отменять? В том-же методе? Так тогда сразу он и отменет, а в самом шедулере нельзя.
 
А если у меня шедулер, который выполняется в репеате 5 раз, это сделано hashmap delay, я добавлю ник игрока, и значение как делай. При каждом выполнеии, добавлю делай+, и если делай > 5, то отменить таску, а где ее отменять? В том-же методе? Так тогда сразу он и отменет, а в самом шедулере нельзя.
Отменить задачу шедулера можно двумя способами:

1) Снаружи: task.cancel(). Для использования необходимо хранить где-то переменную типа BukkitTask

2) Внутри: this.cancel()
Для использования необходимо реализовать BukkitRunnable (вместо использования лямбды)
 
Отменить задачу шедулера можно двумя способами:

1) Снаружи: task.cancel(). Для использования необходимо хранить где-то переменную типа BukkitTask

2) Внутри: this.cancel()
Для использования необходимо реализовать BukkitRunnable (вместо использования лямбды)

А если я создаю шедулер каждому игроку, 1-ый вариант имеет какою-ту возможность?
 
А если я создаю шедулер каждому игроку, 1-ый вариант имеет какою-ту возможность?
Оба варианта доступны независимо от задачи.
Опиши, какую механику ты хочешь получить в конечном итоге, и мы подскажем, как её реализовать технически
 
Оба варианта доступны независимо от задачи.
Опиши, какую механику ты хочешь получить в конечном итоге, и мы подскажем, как её реализовать технически
Телепорт на спавн, задержка 5 секунд перед телепортацией. Каждую секунду отправлять игроку, осталось n сек.
 
Телепорт на спавн, задержка 5 секунд перед телепортацией. Каждую секунду отправлять игроку, осталось n сек.
Создаёшь BukkitRunnable при вводе команды. Внутрь добавляешь числовое поле с числом секунд, оставшихся до телепортации.
Внутри run() выводить оставшееся время. Если время равно нулю, то телепортируешь игрока и отменяешь BukkitRunnable внутри самого себя при помощи this.cancel()
Запускаешь BukkitRunnable с периодом в секунду (20 тиков)
 

Поделиться этой страницей

Назад
Верх