1. Этот сайт использует файлы cookie. Продолжая пользоваться данным сайтом, Вы соглашаетесь на использование нами Ваших файлов cookie. Узнать больше.
  2. Вы находитесь в сообществе Rubukkit. Мы - администраторы серверов Minecraft, разрабатываем собственные плагины и переводим на различные языки плагины наших коллег из других стран.
    Скрыть объявление
Скрыть объявление
В преддверии глобального обновления, мы проводим исследования, которые помогут нам сделать опыт пользования форумом ещё удобнее. Помогите нам, примите участие!

Помогите Работа с BukkitRunnable

Тема в разделе "Разработка плагинов для новичков", создана пользователем Hittcliff, 6 янв 2018.

  1. Автор темы
    Hittcliff

    Hittcliff Активный участник Пользователь

    Баллы:
    66
    Имя в Minecraft:
    Relion128
    Мне нужно дабы код:

    Код:
                        if (b.getX() > valueX[rec] && b.getX() < valueXX[rec]) {
                            if (b.getY() > valueY[rec] && b.getY() < valueYY[rec]) {
                                if (b.getZ() > valueZ[rec] && b.getZ() < valueZZ[rec]) {
    
                                    tested(event, array[rec]);
                                }
                            }
                            rec++;
                        }
    
    выполнялась с другой задержкой, т.е эта часть кода находится в цикле (ниже фул код), и нужно чтобы конкретно этот код что указан выше работал с другой задержкой, допустим выполнился цикл фул кода, но т.к у кода выше другая задержка он не запускается вплодь до тех пор пока не закончится его цикл, ну или просто сделать задержку...



    Код:
            int timer = Integer.parseInt(getConfig().getString("array.time")) * 20;
    
            new BukkitRunnable() {
    
                int rec = 0;
                int rec3 = Integer.parseInt(getConfig().getString("array.value"));
    
                List<String> list = config.getStringList("array.dir");
                String[] array = list.toArray(new String[0]);
    
                @Override
                public void run() {
    
                    if (rec == rec3 || rec > rec3) {
    
                        rec = 0;
                    } else {
    
                        // Позиция 1
                        int[] valueX = new int[rec3];
                        valueX[rec] = Integer.parseInt(getConfig().getString("swarp." + array[rec] + ".x: " + "pos1"));
    
                        int[] valueY = new int[rec3];
                        valueY[rec] = Integer.parseInt(getConfig().getString("swarp." + array[rec] + ".y: " + "pos1"));
    
                        int[] valueZ = new int[rec3];
                        valueZ[rec] = Integer.parseInt(getConfig().getString("swarp." + array[rec] + ".z: " + "pos1"));
    
                        // Позиция 2
                        int[] valueXX = new int[rec3];
                        valueXX[rec] = Integer.parseInt(getConfig().getString("swarp." + array[rec] + ".x: " + "pos2"));
    
                        int[] valueYY = new int[rec3];
                        valueYY[rec] = Integer.parseInt(getConfig().getString("swarp." + array[rec] + ".y: " + "pos2"));
    
                        int[] valueZZ = new int[rec3];
                        valueZZ[rec] = Integer.parseInt(getConfig().getString("swarp." + array[rec] + ".z: " + "pos2"));
                        Location b = player.getLocation();
    
                        if (b.getX() > valueX[rec] && b.getX() < valueXX[rec]) { //От сюда
                            if (b.getY() > valueY[rec] && b.getY() < valueYY[rec]) {
                                if (b.getZ() > valueZ[rec] && b.getZ() < valueZZ[rec]) {
    
                                    tested(event, array[rec]);
                                }
                            }
                            rec++;
                        } //До сюда нужно делать задержку, дабы он работал с другой задержкой... Эта работает раз в 60 секунд..
                    }
                }
            }.runTaskTimer(this, 0L, timer); //Эта допустим работает раз в 3 секунды..
    Я пытался делить на классы, но суть такова, что код выше в любом случае обращается каждые 3 секунды, хотя мне нужно чтобы он делал это с задержкой в 60 секунд.


    Для примера tested к которому обращается код выше:

    Код:
      
     public void tested(PlayerJoinEvent event, String vois) {
            Player player = event.getPlayer();
            player.sendMessage(ChatColor.BLUE + "[DCore]: Вы на территорий: " + vois);
        }
    
    Ах да, почему я просто не укажу основному циклу 60 секунд? Да просто потому, что он каждые 3 секунды ищет игрока, и если находит то должен выполнять действие с задержкой, например запускается песня, и дабы это песня каждые 3 секунды снова - снова - снова не включалась, нужно чтобы была задержка в цикле.
     
  2. Автор темы
    Hittcliff

    Hittcliff Активный участник Пользователь

    Баллы:
    66
    Имя в Minecraft:
    Relion128
    Повторюсь. Я Java изучаю совсем недавно, так что за криворукость кода прошу не писать, со временем научу по уму делать. В конце концов все мы начинали с чего-то)
     
  3. Reality_SC

    Reality_SC Старожил Пользователь

    Баллы:
    123
    Имя в Minecraft:
    Reality_SC
    Тут есть к чему ещё придраться, но по теме -- тут, как мне кажется, есть проблемы с логикой.
    Конфиг постоянно обновляется? Зачем его так часть перечитывать (каждые 60 или 3 секунды)?
    Мешанина из чтения конфига и применением чего-то, ещё и разбить на два таймера, жесть.
    Прочитай весь конфиг заранее, и запускай таймер только на 3 секунды.
     
  4. Reality_SC

    Reality_SC Старожил Пользователь

    Баллы:
    123
    Имя в Minecraft:
    Reality_SC
    Окей, если у тебя в конфиге список кубических территорий, которые могут меняться, и ты хочешь раз в N времени проверять, какие игроки в каких локациях, делай так:
    1. при загрузке плагина читай список территорий в память.
    2. при изменении территории сохраняй весь список в конфиг.
    3. у тебя уже будет под рукой список актуальных территорий, по которому можно итерироваться в обработчике события, и перечитывать ничего не нужно будет. Оставляешь таймер по игроку и всё. А лучше один на всех.
     
  5. Автор темы
    Hittcliff

    Hittcliff Активный участник Пользователь

    Баллы:
    66
    Имя в Minecraft:
    Relion128
    Суть такова, что при заходе игрока на сервер

    А как примерно сей процесс реализовать?
     
  6. Автор темы
    Hittcliff

    Hittcliff Активный участник Пользователь

    Баллы:
    66
    Имя в Minecraft:
    Relion128
    Я могу записать видео в котором покажу что да как работает сейчас, просто для демонстраций сразу и покажу чего я пытаюсь добиться.
     
  7. Автор темы
    Hittcliff

    Hittcliff Активный участник Пользователь

    Баллы:
    66
    Имя в Minecraft:
    Relion128
     
  8. Автор темы
    Hittcliff

    Hittcliff Активный участник Пользователь

    Баллы:
    66
    Имя в Minecraft:
    Relion128
    В видео я более конкретно указал что требуется, запись с первого дубля, просто подключил микро и начал запись. Сорян за херовую дикцию)
     
  9. Автор темы
    Hittcliff

    Hittcliff Активный участник Пользователь

    Баллы:
    66
    Имя в Minecraft:
    Relion128
    swarp:
    Boss:
    'x: pos1': '-214'
    'y: pos1': '40'
    'z: pos1': '44'
    'x: pos2': '-194'
    'y: pos2': '44'
    'z: pos2': '63'
    'sound:': piano.music
    'category:': master
    'sound-time:': '255' //Длительность
    'sound-volume:': '1'
    Boss2:
    'x: pos1': '-215'
    'y: pos1': '41'
    'z: pos1': '87'
    'x: pos2': '-195'
    'y: pos2': '45'
    'z: pos2': '106'
    'sound:': attack.play
    'category:': master
    'sound-time:': '14' //Длительность
    'sound-volume:': '1'
    array:
    value: 2 //Количество данных в массиве
    dir:
    - Boss
    - Boss2
     
  10. deadanykey

    deadanykey Активный участник Пользователь

    Баллы:
    96
    Посмотрел.
    Читаем СРАЗУ весь конфиг в память (HashMap, например). Потом работаем только с памятью.
    При входе игрока следим за PlayerJoinEvent. Также не забываем про телепортирование (эвент не помню).
    Потом с помощью PlayerMoveEvent следим за игроком.

    При входе на территорию играем музыку и стартуем таймер на повторное проигрывание. Перед повтором чекаем, где игрок находится.
     
  11. Reality_SC

    Reality_SC Старожил Пользователь

    Баллы:
    123
    Имя в Minecraft:
    Reality_SC
    Спасибо за подробное изложение, проблема стала понятнее.
    Извиняюсь за паузу, отвлёкся, сейчас вникну в детали и постараюсь дать советы.
     
  12. Автор темы
    Hittcliff

    Hittcliff Активный участник Пользователь

    Баллы:
    66
    Имя в Minecraft:
    Relion128
    Буду очень признателен! :)
     
  13. Автор темы
    Hittcliff

    Hittcliff Активный участник Пользователь

    Баллы:
    66
    Имя в Minecraft:
    Relion128
    Я пока что не умею работать с ХэшМэпом. Я немного не понял смысла ваших советов, простите. :(
     
  14. deadanykey

    deadanykey Активный участник Пользователь

    Баллы:
    96
    Ну вот Вам стимул научиться ))
     
  15. Reality_SC

    Reality_SC Старожил Пользователь

    Баллы:
    123
    Имя в Minecraft:
    Reality_SC
    Вот как вариант для обзора, а дальше десятки их на хабре.
    Вот это тут сразу однозначно. Я бы ещё выделил территорию в класс, назовём для простоты изложения
    Код:
    public class Area {
    
        public String name;
    
        public long x1;
        public long y1;
        public long z1;
        public long x2;
        public long y2;
        public long z2;
    
        public String sound;
        public String category;
        public int soundDuration;
        public double soundVolume;
    }
    Храним их, да, например в ассоциативном массиве, вполне HashMap нас устроит.
    Код:
    Map<String, Area> areas = new HashMap<>(); // В теле класса плагина, или где-нибудь ещё.
    Пишем пару методов, чтения всех территорий из файлов, и записи их туда же.
    Насколько я понял, в конфиге array.value и array.dir используются для определения сохранённых территорий, это не нужно, для получения этих данных уже есть методы у конфига.

    Далее, что делать с игроками.
    Нужно реагировать на три события (на самом деле может быть чуть больше) — вход, движение и выход.
    Ещё нам нужен список игроков, которые "двигались". Я в своё время написал маленький класс и юзал его в разных плагинах. Можешь смело скопипастить себе. У него фактически один метод getMovedPlayersAsync(), вернёт список игроков, которые "двигались" с прошлого запроса.
    И один таймер, например на 3 секунды.
    Таймер будет делать два действия.
    Первое — проверять список "переместившихся игроков", и для них определять, находятся ли они в какой либо зоне, или нет. Если сейчас в зоне, и был в ней (опишем ниже), пропускаем. Если ни в одной из зон, и раньше не был, тоже пропускаем. Далее соответственно либо добавляем, либо удаляем из этой зоны (ниже).
    Когда список игроков внутри каждой зоны сформирован, вторая часть работы таймера - проверить, не пора ли запустить для них действие.
    Для того, чтобы хранить связку Игрок - Зона, в которой он находится в данный момент, можно воспользоваться ещё одним ассоциативным массивом.
     
    Последнее редактирование: 6 янв 2018
  16. Reality_SC

    Reality_SC Старожил Пользователь

    Баллы:
    123
    Имя в Minecraft:
    Reality_SC
    Когда начинал писать текст, в голове была более серьезная реализация именно обработки игрока внутри зоны, но когда дописал, понял, что надо тебе чуть попроще, поэтому будет вариант чуть более нагружающий сервер, но легче реализуемый.

    Итак, у нас есть список пар игрок-зона, и нам нужно для игрока проигрывать в цикле мелодию (или делать какое-то другое действие) раз в M секунд. В основном таймере, который "наблюдает" за посещением зон игроками, в момент Добавления игрока в зону (например, playersPerAreas.put(player, area)) вызываем ещё один метод — создание таймера проигрывания мелодии area.sound с периодом area.soundDuration * 20.
    В теле метода run этого таймера первым делом проверяем, содержится ли всё ещё игрок в карте playersPerAreas.get(player).equals(area). Если нет — отменяем себя вообще и выходим из метода. Если да -- просто играем мелодию. Код короткий и понятный.
    Ну в общем-то это всё.

    Если нужна будет более серьёзная помощь, я буду онлайн минут через 30.
     
  17. Автор темы
    Hittcliff

    Hittcliff Активный участник Пользователь

    Баллы:
    66
    Имя в Minecraft:
    Relion128
    Огосики, сколько информаций сразу наплыло.. аж глаза разбегаются.
     
  18. Автор темы
    Hittcliff

    Hittcliff Активный участник Пользователь

    Баллы:
    66
    Имя в Minecraft:
    Relion128
    Z
    Я понимаю что сейчас я крайне туплю, но насчёт первой части я понял. Таймер который отвечает за отслеживанием игрока:

    Код:
         
    new BukkitRunnable() {       
    @Override
                public void run() {
    
              //По твоей инструкций тут должен быть вызов метода создание таймера. Но ведь если он уже в таймере, то с каждым циклом в ЭТОМ таймере повторно и повторно будет запускаться таймер который кнутри первого...
                }
            }.runTaskTimer(this, 0L, timer); //Эта допустим работает раз в 3 секунды..
    Прости, очень сильно пока туплю с Java)
     
  19. Reality_SC

    Reality_SC Старожил Пользователь

    Баллы:
    123
    Имя в Minecraft:
    Reality_SC
    Там, где комментарий, должно быть условие, что таймер для игрока будет создавать только в том случае, если он попал в зону, в которой не был ранее.
     
  20. Автор темы
    Hittcliff

    Hittcliff Активный участник Пользователь

    Баллы:
    66
    Имя в Minecraft:
    Relion128
    f
    Т.е за пределами таймера создать переменную, которую изменить в таймере и проверять if?

    Код:
    new BukkitRunnable() {      
    @Override
               public void run() {
                  if (b.getX() > valueX[rec] && b.getX() < valueXX[rec]) {
                           if (b.getY() > valueY[rec] && b.getY() < valueYY[rec]) {
                               if (b.getZ() > valueZ[rec] && b.getZ() < valueZZ[rec]) {
                                     ...
    
                               }
                           }
                       }
                }
           }.runTaskTimer(this, 0L, timer);
    
     
    Последнее редактирование: 6 янв 2018

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