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

Помогите Восстановление блока

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

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

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

    Баллы:
    96
    Собственно есть какое-то множество блоков. Если какой либо из них ломают, взрывают и т.д. - нужно превратить его в Бедрок, а через N времени в блок, которым он был раньше(до того как его сломали, взорвали и т.д.).

    Как это сделал я:

    PHP:
        @EventHandler(ignoreCancelled true)
        public 
    void onBlockBreak(final BlockBreakEvent event) {
            final 
    Block block event.getBlock();
            if (
    this.source.getSomeManager().isSomeBlock(block)) {
                
    Bukkit.getPluginManager().callEvent(new SomeBlockBreakEvent(block));
            }
        }
     
        public class 
    SomeBlockBreakEvent extends Event implements Cancellable {
     
            
    //...
     
            
    private final Block block;
            private final 
    Material material//давно делал, даже не помню нахрена материал отдельно сохраняю.

            
    public SomeBlockBreakEvent(Block block) {
                
    this.block block;
                
    this.material block.getType();
            }
      
            
    //...
     
        
    }
     
        private static final 
    = ...;
     
        @
    EventHandler(ignoreCancelled true)
        public 
    void onSomeBlockBreak(SomeBlockBreakEvent event) {
            final 
    Block block event.getBlock();
            final 
    Material old block.getType();
            
    Bukkit.getScheduler().runTask(source, () -> block.setType(Material.BEDROCK));
            
    Bukkit.getScheduler().runTaskLater(source, () -> block.setType(old), N);
        }
    Вопрос, правильна ли реализация и как можно её улучшить?
    p.s. Event действительно нужен. Он тут не просто так.
     
  2. Dereku

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

    Баллы:
    173
    Skype:
    derek_unavailable
    Имя в Minecraft:
    _Dereku
    Я бы таски возвращения блока объеденил в один, ибо слишком много задач не есть здорово. И зачем устанавливать блок в отдельной задаче? Асинхронное событие?
     
  3. Автор темы
    Exception_Prototype

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

    Баллы:
    96
    Нет, не асинхронное, просто старая тупость, которую ещё не поправил.
    По поводу объединения, можно пример? Не догоняю.
     
  4. Cool_boy

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

    Баллы:
    96
    Имя в Minecraft:
    prettydude
    BlockBreakEvent не даёт поменять тип сломанного блока внутри себя.
     
  5. Автор темы
    Exception_Prototype

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

    Баллы:
    96
    https://pastebin.com/7z5D6x7m by @xDark
    Это имелось же ввиду?
     
  6. hyndorik

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

    Баллы:
    98
    Имя в Minecraft:
    hyndo
    а зачем конкурентная мапа? там же асинка нет...
     
  7. AtomicScience

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

    Баллы:
    76
    Имя в Minecraft:
    AtomicScience
    А если перезагрузка? Надо писать в конфиг твои блоки
     
  8. Автор темы
    Exception_Prototype

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

    Баллы:
    96
    Это и так понятно
     
  9. Dereku

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

    Баллы:
    173
    Skype:
    derek_unavailable
    Имя в Minecraft:
    _Dereku
    Ну делаешь один таск. Она по мапе с тиками,локациями и материалами гуляет, тикает тики. Как только тик равен нулю, меняет материал блоку по локации и удаляет entry. Что то сложное?
     
  10. xDark

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

    Баллы:
    96
    В данном примере - нет, но у нас это можно в асинхроне делать, так что...
    (Расчет был на то, что это можн в асинхроне делать, но потом я вспомнил, что на обычном спиготе это нормально не провернуть)
     
  11. alexandrage

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

    Баллы:
    173
    Ибо развалится. Не зря там запрещено так делать.
     
  12. xDark

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

    Баллы:
    96
    Если кое-что заменить, то не развалится :)
     
  13. Reality_SC

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

    Баллы:
    123
    Имя в Minecraft:
    Reality_SC
    Нужно больше информации о задаче, так как могут ведь быть варианты и допущения.
    Если по прикидкам кол-во блоков несерьёзное (материал -- алмаз?), то можно каждый блок сохранить список (и сохранить в конфиг) и назначать ему синхронный таск на восстановление (и выброс из списка + сохранение файла).
    Если большое (ну там типа будут материалы земля, камень и всякий популярный в мире треш), то может вылезти вариант с сохранением в БД (чтобы не потерять весь файл целиком при отключении питания, а только одну транзакцию), и при допустимом разбросе времени определёнными батчами по N шт восстанавливать блоки каждые, например, 10 тиков.
    Если не делать оценку, в каких условиях будет работать плагин, можно огрести или тормозов, или просто неработоспособности.
     
  14. Автор темы
    Exception_Prototype

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

    Баллы:
    96
    Задача простейшая.
    Мини-игра. Есть множество блоков из ~85 объектов. Когда игрок ломает блок, который есть в этом множестве, нужно превратить его в Бедрок, а спустя N времени, вернуть ему первоначальное состояние. В данной теме искался самый оптимальный вариант сделать это.
     
  15. alexandrage

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

    Баллы:
    173
    Ну вот типо такого. Никаких левых ивентов и 1 шедулер.

    Код:
    package Example.runs;
    
    import java.util.Map;
    import java.util.Map.Entry;
    import java.util.concurrent.ConcurrentHashMap;
    
    import org.bukkit.Bukkit;
    import org.bukkit.Material;
    import org.bukkit.scheduler.BukkitRunnable;
    
    public class Scheduler extends BukkitRunnable {
        public static Map<String, Long> blocks = new ConcurrentHashMap<String, Long>();
    
        @Override
        public void run() {
            for (Entry<String, Long> block : blocks.entrySet()) {
                long time = block.getValue();
                String s = block.getKey();
                String[] spl = s.split(":");
                if (time == 100l) {
                    Bukkit.getWorld(spl[0])
                            .getBlockAt(Integer.parseInt(spl[1]), Integer.parseInt(spl[2]), Integer.parseInt(spl[3]))
                            .setType(Material.BEDROCK);
                }
                if (time == 0l) {
                    Bukkit.getWorld(spl[0])
                            .getBlockAt(Integer.parseInt(spl[1]), Integer.parseInt(spl[2]), Integer.parseInt(spl[3]))
                            .setTypeIdAndData(Integer.parseInt(spl[4]), (byte) Integer.parseInt(spl[5]), true);
                    blocks.remove(block.getKey());
                    continue;
                }
                blocks.put(s, time-1);
            }
        }
    }
    Код:
        @EventHandler
        public void on(BlockBreakEvent e) {
            Block b = e.getBlock();
            Location loc = b.getLocation();
            String block = b.getWorld().getName()+":"+loc.getBlockX()+":"+loc.getBlockY()+":"+loc.getBlockZ()+":"+b.getTypeId()+":"+b.getData();
            Scheduler.blocks.put(block, 100l);
        }
    Код:
            Scheduler sd = new Scheduler();
            sd.runTaskTimer(this, 1, 1);
     
  16. HunterGaming

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

    Баллы:
    96
    Имя в Minecraft:
    sqdFendy
    Участник решил поучить девелопера:good:
     
  17. alexandrage

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

    Баллы:
    173
    +1. Так нужно было значит.
     

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