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

HunterGaming

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

Есть какие-то варианты?
 
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());
 
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());
А как поступить с Undo?
 
А что с ним не так? Не вызывает EditSessionEvent? Не должно быть такого.
Нет, он вызывает, но можно ли как-то определить Undo ли произошло или Set? Тип нет наследуемых классов от Extent по типу SetExtent/UndoExtent?
 
Вот смотри, я юзаю это так
Код:
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 стояли блоки, он их не удаляет
                }
            });
        }
    }
 
Вот смотри, я юзаю это так
Код:
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 стояли блоки, он их не удаляет
                }
            });
        }
    }
Ну тк, что можно как-то отследить это?
 
Конкретно в этом событии отследить отмену невозможно, так как оно отвечает за операции нижнего уровня (установку блоков) без возможности определить намерение вызова. Можно попробовать заменить некоторые классы WE, отвечающие за изменения блоков. Но это уже нарушит инкапсуляцию этих классов. В качестве альтернативы есть более простое и примитивное решение - трекать команду /undo перед ее выполнением и добавлять ник игрока в какой-нибудь Set, а после выполнения EditSessionEvent - удалить. Тут тоже есть много подводных камней: это решение будет зависеть от реализации EditSession (событие может и не вызваться, что приведет к утечкам), отмена операций может так же вызываться извне, не только командой, etc.
Я тебе предоставил два варианта решения, какой из них выбрать - решай сам. Я рекомендую первый вариант за счет его гибкости и эффективности.
 
Назад
Верх