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

Помогите WorldEdit#EditSession#countBlocks

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

Метки:
  1. Автор темы
    Exception_Prototype

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

    Баллы:
    96
    Всем ку, такой вопрос возник по WorldEdit 1.7.10:
    Задача: При каждой установке или разрушение блока в привате посчитать количество этого блока в регионе.

    Мой код подсчёта блока в привате:
    PHP:
        private final EditSession editSession;
     
        public 
    SomeClass(World world) {
            
    this.editSession WorldEdit.getInstance().getEditSessionFactory().getEditSession(world, -1);
            
    this.editSession.setFastMode(true);
        }
     
        public 
    int countBlock(Region regionMaterial materialshort data) {
            return 
    this.editSession.countBlocks(regionCollections.singleton(new BaseBlock(material.getId(), data)));
        }
    Я задался вопросом, как лучше использовать EditSession:
    1. Создавать для каждого просчёта новую - отпадает сразу, глупость.
    2. Получать EditSession игрока, для которого идёт просчёт.
    3. Создать один экземпляр EditSession при запуске плагина и считать всё в нем.

    Больше всего нравится третий вариант, но тут возникает вопрос, будет ли дополнительная нагрузка, если все подсчёты блоков будут происходить в одном EditSession?
    Что думаете? Как лучше поступить?

    P.S.
    - увы, но нет возможности поставить FAWE.
    - fastmode(true) вырубает истории(они нафиг не нужны).
     
    Последнее редактирование: 19 мар 2019
  2. LuckyZeeRo

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

    Баллы:
    96
    Имя в Minecraft:
    i0xHeX
    В любом случае ты получишь итерацию по блокам в регионе синхронно, что даст тебе нехилую нагрузку в общей ситуации. Разве что распределять подсчеты по лимитам на какое то время. И скорее EditSession нафиг не нужен, только дополнительные ресурсы на парсинг блоков.
     
  3. Автор темы
    Exception_Prototype

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

    Баллы:
    96
    WE сделает это на много быстрей чем ручной просчёт.
     
  4. LuckyZeeRo

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

    Баллы:
    96
    Имя в Minecraft:
    i0xHeX
    Каким образом позволь спросить?
     
  5. Автор темы
    Exception_Prototype

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

    Баллы:
    96
    Ну почему к примеру при установки огромного кол-ва блоков сервер не крашится, а при ручном setType() ляжет? У него свои оптимизации, очереди, кеши.
     
  6. MurlikMurlik

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

    Баллы:
    96
    По моему такое только у fawe есть, никак у we.
     
  7. LuckyZeeRo

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

    Баллы:
    96
    Имя в Minecraft:
    i0xHeX
    Именно так. Если поставить через WE достаточно блоков, сервер зафризит до таймаута.
    Просто возьми и глянь сурсы, там любая операция идет через Visitor, который итерирует каждый блок региона и выполняет заданную функцию. Ничего сверх особенного. Единственное это свои врапперы и т.п.
     
    Последнее редактирование: 20 мар 2019
  8. LuckyZeeRo

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

    Баллы:
    96
    Имя в Minecraft:
    i0xHeX
    Но вернемся к вопросам. А почему создавать отдельную сессию для каждого просчета плохо? Вроде в ней нет ничего такого, чтобы могло нагрузить хотя бы на миллисекунду. Короче проблема с производительностью скорее возникнет на этапе массивного подсчета блоков во многих регионах (здесь решения через кеш и распределения подсчета блоков на время, кстати можешь переопределить сессию и немного оптимизировать что нужно), а создавать сессии можно и не жалко. Все равно их GC уберет как только отпадут.

    Иногда жадность к ресурсам и памяти может заесть так, что за каждый байт и наносекунду сидишь днями думаешь над оптимизациями. Не всегда это хорошо. Важно оценивать все объективно.
     
    Последнее редактирование: 20 мар 2019
  9. alexandrage

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

    Баллы:
    173
    Так он и оценивает. К чему создавать постоянно сессию, когда она делает одно и то же.
    Одна сессия на один плагин, больше нам и не нужно.
     
  10. Автор темы
    Exception_Prototype

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

    Баллы:
    96
    Окей, допустим. Планируется лимитировать только TileEntity, поэтому, что если брать рг и пробегаться по его чанкам и в каждом чанке делать chunk.getTileEntities(). Как бы по всем блокам не бегаем, только по TileEntiy. Что скажите? Как Вам такой вариант?

    PHP:
    public int getCount(World worldProtectedRegion regionMaterial materialbyte data) {

            final 
    int minX region.getMinimumPoint().getBlockX() >> 4;
            final 
    int minZ region.getMinimumPoint().getBlockZ() >> 4;
            final 
    int maxX region.getMaximumPoint().getBlockX() >> 4;
            final 
    int maxZ region.getMaximumPoint().getBlockZ() >> 4;

            
    //debug(String.format("Request to search: %s %d", material.name(), data));

            
    int count 0;

            for (
    int x minX<= maxXx++) {
                for (
    int z minZ<= maxZz++) {
                    final 
    Chunk chunk world.getChunkAt(xz);
                    final 
    BlockState[] tiles chunk.getTileEntities();
                    if (
    tiles != null) {
                        for (
    BlockState blockState tiles) {
                            final 
    Block block blockState.getBlock();
                            
    //debug(String.format("Tile: %s %d", block.getType().name(), block.getData()));
                            
    if ((block.getType() == material)) {
                                if ((
    data == -1) || (block.getData() == data)) {
                                    
    count++;
                                }
                            }
                        }
                    }
                }
            }

            
    //debug("getCount#count: " + count);
            
    return count;
        }
     
    Последнее редактирование: 20 мар 2019
  11. LuckyZeeRo

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

    Баллы:
    96
    Имя в Minecraft:
    i0xHeX
    Можно, если тебе конечно же неважно, входит тот блок в чанке в регион или нет. Плюс есть идеи оптимизации:
    Код:
    public int getCount(World world, ProtectedRegion region, Material material, byte data) {
        int minX = region.getMinimumPoint().getBlockX() >> 4;
        int minZ = region.getMinimumPoint().getBlockZ() >> 4;
        int maxX = region.getMaximumPoint().getBlockX() >> 4;
        int maxZ = region.getMaximumPoint().getBlockZ() >> 4;
        
        int count = 0;
        
        for (int x = minX; x <= maxX; x++) {
            for (int z = minZ; z <= maxZ; z++) {
                Chunk chunk = world.getChunkAt(x, z);
                for (BlockState blockState : chunk.getTileEntities()) {
                    if (blockState.getType() == material && (data == -1 || blockState.getRawData() == data)) {
                        count++;
                    }
                }
            }
        }
        
        return count;
    }
    Еще одно, скорее всего можно пихать BlockStat'ы куда нибудь на обработку в асинхронном потоке, так как это уже снепшоты блоков, а вот получение блока из BlockState уже ведет к повторному обращению к чанку.
     
  12. Автор темы
    Exception_Prototype

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

    Баллы:
    96
    Спасибо за оптимизированный вариант.

    По поводу того, что входил тот блок в чанке в регион, я уже думал над этим, но всё ещё не определился окончательно. По сути - лимитированные блоки нельзя будет поставить за регион(т.е. в глобал). По идее мы ничего не упустим, но если ставить вопрос ребром, то я бы хотел знать, что даст больше нагрузки: проверка того, что TileEntity входит в регион или редкая проверка лишних блоков, которые не вошли в регион но находятся в чанке? Лично я склоняюсь ко второму варианту, а что думаете Вы по этому поводу?

    async
    Хм, не знал, это можно использовать. Например для async вывода лимитированных блоков игроку(например показать координаты этих блоков, по команде), но в BlockPlaceEvent мне кажется это никак не поможет или я ошибаюсь?
     
  13. LuckyZeeRo

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

    Баллы:
    96
    Имя в Minecraft:
    i0xHeX
    Я тоже думаю что второе.

    Если ты хочешь юзать асинхрон, в любом случае выйдешь за пределы события.
     

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