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

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 N = ...;
 
    @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 действительно нужен. Он тут не просто так.
 
Я бы таски возвращения блока объеденил в один, ибо слишком много задач не есть здорово. И зачем устанавливать блок в отдельной задаче? Асинхронное событие?
 
Я бы таски возвращения блока объеденил в один, ибо слишком много задач не есть здорово. И зачем устанавливать блок в отдельной задаче? Асинхронное событие?
Нет, не асинхронное, просто старая тупость, которую ещё не поправил.
По поводу объединения, можно пример? Не догоняю.
 
А если перезагрузка? Надо писать в конфиг твои блоки
 
По поводу объединения, можно пример? Не догоняю.
Ну делаешь один таск. Она по мапе с тиками,локациями и материалами гуляет, тикает тики. Как только тик равен нулю, меняет материал блоку по локации и удаляет entry. Что то сложное?
 
а зачем конкурентная мапа? там же асинка нет...
В данном примере - нет, но у нас это можно в асинхроне делать, так что...
(Расчет был на то, что это можн в асинхроне делать, но потом я вспомнил, что на обычном спиготе это нормально не провернуть)
 
В данном примере - нет, но у нас это можно в асинхроне делать, так что...
(Расчет был на то, что это можн в асинхроне делать, но потом я вспомнил, что на обычном спиготе это нормально не провернуть)
Ибо развалится. Не зря там запрещено так делать.
 
Нужно больше информации о задаче, так как могут ведь быть варианты и допущения.
Если по прикидкам кол-во блоков несерьёзное (материал -- алмаз?), то можно каждый блок сохранить список (и сохранить в конфиг) и назначать ему синхронный таск на восстановление (и выброс из списка + сохранение файла).
Если большое (ну там типа будут материалы земля, камень и всякий популярный в мире треш), то может вылезти вариант с сохранением в БД (чтобы не потерять весь файл целиком при отключении питания, а только одну транзакцию), и при допустимом разбросе времени определёнными батчами по N шт восстанавливать блоки каждые, например, 10 тиков.
Если не делать оценку, в каких условиях будет работать плагин, можно огрести или тормозов, или просто неработоспособности.
 
Нужно больше информации о задаче, так как могут ведь быть варианты и допущения.
Если по прикидкам кол-во блоков несерьёзное (материал -- алмаз?), то можно каждый блок сохранить список (и сохранить в конфиг) и назначать ему синхронный таск на восстановление (и выброс из списка + сохранение файла).
Если большое (ну там типа будут материалы земля, камень и всякий популярный в мире треш), то может вылезти вариант с сохранением в БД (чтобы не потерять весь файл целиком при отключении питания, а только одну транзакцию), и при допустимом разбросе времени определёнными батчами по N шт восстанавливать блоки каждые, например, 10 тиков.
Если не делать оценку, в каких условиях будет работать плагин, можно огрести или тормозов, или просто неработоспособности.
Задача простейшая.
Мини-игра. Есть множество блоков из ~85 объектов. Когда игрок ломает блок, который есть в этом множестве, нужно превратить его в Бедрок, а спустя N времени, вернуть ему первоначальное состояние. В данной теме искался самый оптимальный вариант сделать это.
 
Ну вот типо такого. Никаких левых ивентов и 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);
 
Назад
Верх