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

Помогите Получить измененные блоки одной операции WE

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

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

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

    Баллы:
    96
    Имя в Minecraft:
    sqdFendy
    Здравствуйте, форумчане. У меня появилась ситуация, в которой мне нужно получать измененные блоки одной операции WorldEdit и записывать их в базу данных. С записью проблем не будет, но как получить эти самые блоки, вот не знаю. Гуглил, ничего путевого не нашел пока что.

    Есть какие-то варианты?
     
  2. alexandrage

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

    Баллы:
    173
    EditSessionEvent тебя устроит? Можно получить блоки до и после замены. А так же подменить саму замену, если требуется.
    Код:
    public class DelegateExtent extends AbstractDelegateExtent {
        public DelegateExtent(Extent extent) {
            super(extent);
        }
    
        @Override
        public <T extends BlockStateHolder<T>> boolean setBlock(BlockVector3 location, T block) throws WorldEditException {
            //TODO тут твои действия.
            return super.setBlock(location, block);
        }
    }
    Код:
    public class MyEventHandler {
        @Subscribe
        public void onEditSessionChange(EditSessionEvent event) {
            if (event.getStage() == EditSession.Stage.BEFORE_CHANGE) {
                event.setExtent(new DelegateExtent(event.getExtent()));
            }
        }
    }
    Код:
    WorldEdit.getInstance().getEventBus().register(new MyEventHandler());
     
  3. Автор темы
    HunterGaming

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

    Баллы:
    96
    Имя в Minecraft:
    sqdFendy
    А как поступить с Undo?
     
  4. alexandrage

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

    Баллы:
    173
    А что с ним не так? Не вызывает EditSessionEvent? Не должно быть такого.
     
  5. Автор темы
    HunterGaming

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

    Баллы:
    96
    Имя в Minecraft:
    sqdFendy
    Нет, он вызывает, но можно ли как-то определить Undo ли произошло или Set? Тип нет наследуемых классов от Extent по типу SetExtent/UndoExtent?
     
  6. Автор темы
    HunterGaming

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

    Баллы:
    96
    Имя в Minecraft:
    sqdFendy
    Вот смотри, я юзаю это так
    Код:
    private StorageManager storageManager;
    
        public EditSessionListener(LockBlock plugin) {
            storageManager = plugin.getStorageManager();
        }
    
        public void load() {
            WorldEdit.getInstance().getEventBus().register(this);
        }
    
        @Subscribe
        public void onEditSession(EditSessionEvent e) {
            if (e.getStage() == EditSession.Stage.BEFORE_CHANGE) {
                e.setExtent(new AbstractLoggingExtent(e.getExtent()) {
    
                    @Override
                    protected void onBlockChange(Vector position, BaseBlock newBlock) {
                        super.onBlockChange(position, newBlock);
    
                        World world = Bukkit.getWorld(e.getWorld().getName());
                        if (world == null) return;
                        Location location = new Location(world, position.getBlockX(), position.getBlockY(), position.getBlockZ());
    
                        Material originalMaterial = location.getBlock().getType();
    
                        if (newBlock.getId() != 0)
                            storageManager.getIStorage().put(location, originalMaterial); //добавляется каждый сетнутый блок в лист
                        else
                            storageManager.getIStorage().remove(location); //удаляется, т.е. если просан //set 0 или /undo, но когда мы пишем /undo то, если в pos1 и pos2 стояли блоки, он их не удаляет
                    }
                });
            }
        }
    
     
  7. Автор темы
    HunterGaming

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

    Баллы:
    96
    Имя в Minecraft:
    sqdFendy
    Ну тк, что можно как-то отследить это?
     
  8. Автор темы
    HunterGaming

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

    Баллы:
    96
    Имя в Minecraft:
    sqdFendy
  9. CatCoder

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

    Баллы:
    76
    Имя в Minecraft:
    CatCoder
    Конкретно в этом событии отследить отмену невозможно, так как оно отвечает за операции нижнего уровня (установку блоков) без возможности определить намерение вызова. Можно попробовать заменить некоторые классы WE, отвечающие за изменения блоков. Но это уже нарушит инкапсуляцию этих классов. В качестве альтернативы есть более простое и примитивное решение - трекать команду /undo перед ее выполнением и добавлять ник игрока в какой-нибудь Set, а после выполнения EditSessionEvent - удалить. Тут тоже есть много подводных камней: это решение будет зависеть от реализации EditSession (событие может и не вызваться, что приведет к утечкам), отмена операций может так же вызываться извне, не только командой, etc.
    Я тебе предоставил два варианта решения, какой из них выбрать - решай сам. Я рекомендую первый вариант за счет его гибкости и эффективности.
     
  10. alexandrage

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

    Баллы:
    173
    А там еще и команда redo имеется. Думаю проще забить и логировать все подряд.
     

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