Хостинг серверов Minecraft playvds.com
  1. Вы находитесь в русском сообществе Bukkit. Мы - администраторы серверов Minecraft, разрабатываем собственные плагины и переводим на русский язык плагины наших собратьев из других стран.
    Скрыть объявление

Помогите Как сделать задержку?

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

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

    CHAMPION Ньюби Пользователь

    Баллы:
    1
    Имя в Minecraft:
    ReeTap
    Тупой вопрос, но...
    Как сделать задержку между этими командами?)
    Т.е, мне нужно чтобы сначала выполнилась первая команда, и через 10 секунд вторая
    player.getInventory().addItem(new ItemStack(Material.DIAMOND_BLOCK));
    player.getInventory().addItem(new ItemStack(Material.CAKE));
     
  2. Хостинг MineCraft
    <
  3. _EnderWorld_

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

    Баллы:
    78
    Имя в Minecraft:
    Steve
    Во первых этот код это не команда.
    Конструктор команды делается вот так:
    Код:
    public boolean onTest(CommandSender sender, Command cmd, String label, String[] args) {
    
    Player p = (Player) sender;                       // Узнаем что игрок отправитель команды
    
    if(!(p.hasPermission("Твой пермишен"))) {               // Если игрок не имеет право
             return;                                   // Возвращаем действия
    }
     
    if(label.equalsIgnoreCase("Твоя команда тут") {          // Узнаем какая команда будет выдавать код
    
          // Твой код здесь
    
    }
    
    
    
    return false;
    
    
     
  4. Reality_SC

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

    Баллы:
    123
    Имя в Minecraft:
    Reality_SC
    Код:
    ...
    player.getInventory().addItem(new ItemStack(Material.DIAMOND_BLOCK));
    getServer().getScheduler().runTaskLater(new Runnable()
    {
       @Override
       public void run()
       {
          player.getInventory().addItem(new ItemStack(Material.CAKE));
       }
    }, 20 * 10);
    Писал без IDE, мог косячнуть.
     
  5. Автор темы
    CHAMPION

    CHAMPION Ньюби Пользователь

    Баллы:
    1
    Имя в Minecraft:
    ReeTap
    Кучу ошибок выдаёт, не могу их убрать)[DOUBLEPOST=1447059690,1447059649][/DOUBLEPOST]
    Мне нужно сделать задержку, а не пермишены проверить)
     
  6. Reality_SC

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

    Баллы:
    123
    Имя в Minecraft:
    Reality_SC
    Чтобы убрать ошибку, нужно её понять.
     
  7. DPOH-VAR

    DPOH-VAR Старожил Пользователь

    Баллы:
    153
    Skype:
    dpohvar
    1) Не надо проверять пермиты на команду в коде команды.
    Потому что это конфигурякается в plugin.yml.
    Проверку пермитов нужно делать только при сложной логике.
    Если вы видели такой подход в туториалах - забудьте, эта проверка лишняя.

    2) Не надо проверять название команды.
    Потому что это тоже конфигурякается в plugin.yml.
    Имя команды и ее алиасы задаются в конфиге. Если код исполняется, значит он вызван по вашей команде или по алиасу.
    Проверку имени команды надо делать только в случаях:
    • если вам нужно отличать название команды или алиасов, что не требуется в 99% случаев.
    • если вы говнокодите и вешаете один и тот же обработчик на две разных команды.
    • если вы используете два разных инстанса одного класса как обработчики двух разных команд. Но тогда поведение должно зависеть от свойств инстанса, а не от названия команды.
    Если вы видели такой подход в туториалах - забудьте, эта проверка лишняя.

    3) Player p = (Player) sender;
    Всегда предусматривайте возможность того, что команду может исполнить не только игрок.
    А вот тут точно нужна проверка класса. Или, если любите говнокодить, то try-catch
    Простой вариант:
    Код:
    if (!(sender instanceof Player) return false)
    4) public boolean onTest
    Всё-таки onCommand
    И метод всегда должен возвращать булево:
    true - наша команда отработала как надо, все ок.
    false - произошла ошибка. Sender автоматически получит сообщение со справкой о команде.

    Учтите, что метод runTaskLater добавляет задачу в планировщик. Задача добавится, однако остальной код (ниже) продолжит исполняться сейчас.
     
  8. Dereku

    Dereku Старожил

    Баллы:
    173
    Skype:
    derek_unavailable
    Имя в Minecraft:
    _Dereku
    THIS.
    Хоть кто то догадался это написать. Я б даже лайк поставил. Два лайка.
     
  9. LaoTheLizard

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

    Баллы:
    103
    Skype:
    sgp_the_controller
    Кстати, эти ошибки делает большинство.
     
  10. SaMEC

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

    Баллы:
    173
    Skype:
    support.meedway
    Имя в Minecraft:
    Nick
    Вот вам шаблончик, для создания задержки другим способом.
    Код:
    package ru.meedway.samec;
    
    import java.util.HashMap;
    
    public class Cooldown {
        private String player;
        private long cooldown;
        private String key;
        public static HashMap<String, Cooldown> cooldowns = new HashMap();
       
        public Cooldown(String player, long cooldown, String key){
            this.player = player;
            this.cooldown = cooldown;
            this.key = key;
        }
       
        public String getPlayer(){
            return this.player;
        }
       
        public long getCooldown(){
            return this.cooldown;
           
        }
       
        public String getKey(){
            return this.key;
        }
       
        public static void setCooldown(String player, long cooldown, String title){
            cooldowns.put(player + title, new Cooldown(player, System.currentTimeMillis()+ cooldown, title));
        }
       
        public static boolean hasCooldown(String player, String title){
            if(cooldowns.get(player + title) == null){
                return false;
            }
            return ((Cooldown)cooldowns.get(player + title)).getCooldown() > System.currentTimeMillis();
        }
       
        public static long getCooldown(String player, String title){
            return ((Cooldown)cooldowns.get(player + title)).getCooldown() - System.currentTimeMillis();
        }
    }
    
    После просто вставляете куда вам вздумается, данную конструкцию, просто меняя название таблицы.
    Код:
    
            if(Cooldown.hasCooldown(player.getName(), "guns")){
                player.sendMessage("Ожидайте " + Cooldown.getCooldown(player.getName(), "guns"));
                e.setCancelled(true);
                return;
            }
          Cooldown.setCooldown(player.getName(), 5 * 1000L, "guns");
    
    Меньше нагрузка, по сравнению с Scheduler.
     
  11. Dereku

    Dereku Старожил

    Баллы:
    173
    Skype:
    derek_unavailable
    Имя в Minecraft:
    _Dereku
    Не вижу никаких runnable. Отсюда выходит, что данный код должен чем то вызываться. Костыль для Scheduler, который будет использоваться Scheduler'ом?
     
  12. DPOH-VAR

    DPOH-VAR Старожил Пользователь

    Баллы:
    153
    Skype:
    dpohvar
    Это кулдаун. Ну или паттерн throttle without trailing.
    В определенном месте ставится семафор с таймером и исполняется код. При следующем вызове, если семафор установлен, код не исполняется. Предназначение совсем другое, не то, что имел в виду ТС.
     
  13. CraftCoder

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

    Баллы:
    108
    Имя в Minecraft:
    CraftCoderr
    Если у нескольких команд один executor, то проверять нужно.
     
  14. DPOH-VAR

    DPOH-VAR Старожил Пользователь

    Баллы:
    153
    Skype:
    dpohvar
    Повторю: это основная ошибка новичков.

    Юный девелопер, который решил заняться плагинами, и абсолютно не знаком с java, сделает свой первый Hello world путём копипасты из туториала. Сам туториал, к сожалению, ничего толком не объясняет, а просто указывает, как нужно писать, при этом сам состоит из говнокода.
    Всё, на что опирается новичок - это конструкции языка: if, for, while и другие. На них можно построить всю логику плагина, но этого недостаточно, чтобы писать хороший, человекочитаемый и поддерживаемый код.

    Проблема туториалов в том, что там не объясняется архитектура Bukkit API. К примеру приведу инструкцию по созданию обработчика команд:
    - Создай класс MyExecutor implements CommandExecutor
    - зарегистрируй его так: getCommand("basic").setExecutor(new MyExecutor());
    - Создай в нем метод onCommand и напишите в него говнокод как в туториале
    Всё. Этого достаточно, все будет работать.

    Но на самом деле все сложнее, и этот пример - всего лишь самый простой способ реализовать обработчик команды. Чтобы понять это полностью, нужно иметь опыт в использовании ООП. Новички же не будут заморачиваться, и начнут говнокодить внутри метода обработчика, делая все строго по инструкции.

    давайте реализуем команды /sendRed и /sendBlue, которые будут писать сообщение в чат красным и синим цветом соответственно.
    Решение в лоб, как поступит новичок:
    Код:
    // Plugin onload:
    getCommand("sendRed").setExecutor(new ColorExecutor());
    getCommand("sendBlue").setExecutor(new ColorExecutor());
    // ColorExecutor:
    public boolean onCommand(CommandSender sender, Command cmd, String commandLabel, String[] args){
        if (args.length >= 1) {
            if (cmd.getName().equals("sendRed")){
               sender.sendMessage(ChatColor.RED.toString() + args[0])
               return true;
           }
           if (cmd.getName().equals("sendBlue")){
               sender.sendMessage(ChatColor.RED.toString() + args[0])
               return true;
           }
        }
        return false;
    }
    а вот более практичный способ:
    Код:
    // Plugin onload:
    getCommand("sendRed").setExecutor(new ColorExecutor(ChatColor.RED));
    getCommand("sendBlue").setExecutor(new ColorExecutor(ChatColor.BLUE));
    // ColorExecutor:
    private ChatColor color;
    public ColorExecutor(ChatColor color){
        this.color = color;
    }
    public boolean onCommand(CommandSender sender, Command cmd, String commandLabel, String[] args){
        if (args.length < 1) return false;
        sender.sendMessage(this.color.toString() + args[0])
        return true;
    }
    Таким образом, если в будущем вам приспичит создать команду /sendYellow, достаточно будет всего лишь добавить ее в plugin.yml и прописать
    Код:
    getCommand("sendYellow").setExecutor(new ColorExecutor(ChatColor.YELLOW));
    и не нужно править код листенера.

    PS: Этот код скорее бесполезный. Есть еще много способов улучшить этот код, и не нужно на эту тему холиварить. Основной идеей было то, что практичность кода больше зависит от опыта программиста, чем от реализации API, и этого невозможно добиться, изучая только туториалы.

    PSS: Есть еще и другие способы зарегистрировать команду, кроме как через setExecutor(CommandExecutor). Например, чтобы не прописывать команду в plugin.yml вовсе. Но это требуется далеко не всем плагинам и требует хороших знаний Bukkit API.

    Если вы пишете один обработчик для нескольких команд, то:
    • либо вы говнокодите от недостатка знаний ООП. У вас получится сильносвязанный код, содержащий потенциальные ошибки при его изменении и переиспользовании.
    • либо вы делаете как в примере выше, и вас не волнует название команды внутри обработчика
    Выводы такие:
    • Изучайте язык, а не только его синтаксис.
    • Не опирайтесь на туториал полностью. В реальной практике туториалы бесполезны. Читайте доки по Bukkit API.
    • Экспериментируйте! Опыт растет не в бороде, а на руках.
    • Еще раз изучайте язык и пишите хороший слабосвязаный человекочитаемый код.
     
    Последнее редактирование: 11 ноя 2015
  15. Dolikan

    Dolikan Ньюби Пользователь

    Баллы:
    1
    Честно, говоря, обработка команд - одна из главных проблем в Bukkit API. У меня нередко выходит говнокод именно в командах из-за всяких проверок аргументов, прав, подкомманд, кто отправил и т.д.

    Чтобы навести порядок в командах, стоит использовать либу от sk89q.
     
  16. Dereku

    Dereku Старожил

    Баллы:
    173
    Skype:
    derek_unavailable
    Имя в Minecraft:
    _Dereku
    Можно обойтись и без неё, если грамотно форматировать код.
     

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