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

Помогите Ащипка при спавне энтити в CreatureSpawnEvent...

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

  1. slavik123123123

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

    Баллы:
    143
    Имя в Minecraft:
    Leymooooooooooo
    разве каждый файл, это свой чанк?
     
  2. Хостинг MineCraft
    <
  3. Автор темы
    Mr_RoboMan

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

    Баллы:
    123
    Ыыы... Если нет, то.. Мне нужен другой способ, как получить все чанки..[DOUBLEPOST=1467133603,1467130766][/DOUBLEPOST]Хотя да, че мне кажется нафейлил я жоСССка..
    И это реально не чанки а что-то другое((
     
  4. fall.us

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

    Баллы:
    76
    Имя в Minecraft:
    fallus
    В папке с миром хранятся файлы регионов, а в них хранятся данные о чанках. Вся информация хранится в сжатом виде в формате NBT.
     
  5. Автор темы
    Mr_RoboMan

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

    Баллы:
    123
    Ыыы... Спасибо, а можно продолжение?)
    Ну типо как все это прочитать?
    По крайней мере просто вынуть коорды всех чанков...
     
  6. Reality_SC

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

    Баллы:
    123
    Имя в Minecraft:
    Reality_SC
    Можно просто предположить, что если есть файл региона, то в нём есть все соответствующие чанки.
    В файле региона содержится 32×32 чанка, регионы тоже имеют свои целочисленные знаковые номера в имени файла.
     
  7. Автор темы
    Mr_RoboMan

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

    Баллы:
    123
    Ыыы.. Ну окей, предположили.. А вынуть эти коорды чанков то как?(
     
  8. Saharo4ek

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

    Баллы:
    76
    Имя в Minecraft:
    tin
    Охринеть вы изверги
     
  9. Автор темы
    Mr_RoboMan

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

    Баллы:
    123
    Не "мы" а я. Я один такой :D
     
  10. Reality_SC

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

    Баллы:
    123
    Имя в Minecraft:
    Reality_SC
    Вынимать через сложную формулу, которую не всем рассказывают в школе: умножение.

    chunkAbsoluteX = regionX * 32 + chunkInRegionX;
    blockAbsoluteX = chunkAbsoluteX * 16 + blockInChunkX,
    где chunkInRegionX от 0 до 31, blockInChunkX от 0 до 15, regionX берется из названия файла.
     
  11. fall.us

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

    Баллы:
    76
    Имя в Minecraft:
    fallus
    Кроме X есть еще Z. Или наш кубач в 2д перешел?[DOUBLEPOST=1467135620,1467135501][/DOUBLEPOST]http://wiki.vg/Map_Format
     
  12. Reality_SC

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

    Баллы:
    123
    Имя в Minecraft:
    Reality_SC
    Товарищи, которые не могут для Z сделать по аналогии, вообще желательны к покиданию данного раздела.
     
  13. Автор темы
    Mr_RoboMan

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

    Баллы:
    123
    Ладно, сегодня уже мозг не варит, завтра утром свежим взглядом гляну - авось пойму чего :D
     
  14. Dereku

    Dereku Старожил

    Баллы:
    173
    Skype:
    derek_unavailable
    Имя в Minecraft:
    _Dereku
    Что то ТС совсем фигнёй занимается.
    Имеем регион. Регион есть две точки в 3D пространстве - A и B. Имея эти две точки, мы можем получить чанки C и D. К примеру, C = 31,-16; а D = 29,-20. Элементарным двойным циклом проходим по этим двум точкам (предварительно узнав максимальные и минимальные значения - чтобы не разъехалось) и заносим координаты в лист для регена. После либо через шедулер, либо другим макаром, "регеним" чанк - из чистого мира забираем чанк по нашим координатам (если нужно, а оно нужно, загружаем чанк в память) и ставим блоки из чистого чанка в старый. Как закончили - выгружаем чанк из памяти. И так проходим весь лист пока он не станет пустым.
    Теперь вопрос. Зачем пытаться загружать мир ручками (привет, не меренные траты памяти) костыльными методами, когда можно нагрузить этой работой сам сервер?
     
  15. Автор темы
    Mr_RoboMan

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

    Баллы:
    123
    Я в общем решил просто протестировать не крашнется ли сервер от такого...
    И он все-таки крашнулся с сообщением типо "Сервер перестал отвечать на запросы"...
    Как правильно перегенерировать все? Чанки и т.д. у меня уже есть, осталось только понять как это все сделать без краша сервера..
    Код:
        @EventHandler
        public void test(AsyncPlayerChatEvent event) {
            if (event.getMessage().equalsIgnoreCase("START")) {
                List<String> chunks = chunkConfig.getStringList("CHUNKS");
                World world1 = Bukkit.getWorld("world1");
                World world2 = Bukkit.getWorld("world2");
                for (String ch : chunks) {
                    int x = Integer.valueOf(ch.split("\\|")[0]);
                    int z = Integer.valueOf(ch.split("\\|")[1]);
                    Bukkit.getScheduler().runTask(GWMServerPlugin.plugin, () -> {
                        Chunk chunk1 = world1.getChunkAt(x, z);
                        if (chunk1.isLoaded()) chunk1.load();
                        Chunk chunk2 = world2.getChunkAt(x, z);
                        if (chunk2.isLoaded()) chunk2.load();
                        for (int xLoc = 0; xLoc < 16; xLoc++) {
                            for (int zLoc = 0; zLoc < 16; zLoc++) {
                                for (int yLoc = 0; yLoc < 256; yLoc++) {
                                    Block block1 = chunk1.getBlock(xLoc, yLoc, zLoc);
                                    Block block2 = chunk2.getBlock(xLoc, yLoc, zLoc);
                                    block1.setTypeIdAndData(block2.getTypeId(), block2.getData(), true);
                                }
                            }
                        }
                    });
                }
            }
        }
    
    [DOUBLEPOST=1467174180,1467173898][/DOUBLEPOST](Когда регенил один чанк (в котором стоит игрок) ничего страшного не было..)[DOUBLEPOST=1467177704][/DOUBLEPOST]Хотя я лучше решил регенить по блоку (я ж все-равно для себя пишу, нафиг я парюсь..).
    Код:
        public void startRegeneration() {
            Bukkit.getScheduler().runTask(GWMServerPlugin.plugin, () -> {
                for (Player p : Bukkit.getOnlinePlayers()) p.kickPlayer(ChatColor.translateAlternateColorCodes('&',
                        GWMServerPlugin.plugin.languageConfig.getString("REGENERATING_WORLD")));
                regenerating = true;
                int x = minX;
                int x2 = maxX;
                int z = minZ;
                int z2 = maxZ;
                for (; x <= x2; x++) {
                    for (; z <= z2; z++) {
                        for (int y = 0; y < 256; y++) {
                            Block block1 = world1.getBlockAt(x, y, z);
                            Block block2 = world2.getBlockAt(x, y, z);
                            if (!block1.getChunk().isLoaded()) block1.getChunk().load();
                            if (!block2.getChunk().isLoaded()) block2.getChunk().load();
                            block1.setTypeIdAndData(block2.getTypeId(), block2.getData(), false);
                            if (block1.getChunk().isLoaded()) block1.getChunk().unload();
                            if (block2.getChunk().isLoaded()) block2.getChunk().unload();
                        }
                    }
                }
                regenerating = false;
            });
        }
    
    Но проблема все та-же, надо это делать как-то поочередено, ибо сервер залагивает и посылает на..
    А вот как это делать поочередно, я не пойму...
     
  16. Reality_SC

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

    Баллы:
    123
    Имя в Minecraft:
    Reality_SC
    1. Регенерацию нужно раскидывать во времени по серверным тикам. Нельзя просто так взять и регенерировать всю карту за один тик.
    2. Нельзя это делать вне основного серверного потока. Вне его можно только планировать действия на будущие такты.
    3. Регенерация одного чанка (где стоит игрок) — в целом, терпимая разовая задача, и от неё сервер повиснуть как следует не сможет.
    План действий такой:
    1. Составить для себя список всех чанков, которые нужно в ближайшее время проверить/регенерировать.
      Зная фактические размеры своей карты (+/- x, +/- z) можно взять и заполнить список всеми возможными координатами чанков.
    2. По тактам регенерировать отдельные чанки из списка, возможно даже кусками. Например по 1/2 или 1/4 чанка. Под регеном я подразумеваю копипасту блоков из одного мира в другой.
     
  17. Автор темы
    Mr_RoboMan

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

    Баллы:
    123
    1. Вот мне интересно как его составить... Точные размеры моей карты это int minX, maxX, minZ, MaxZ, и как мне из этого сделать список чанков?(
     
  18. Reality_SC

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

    Баллы:
    123
    Имя в Minecraft:
    Reality_SC
    Поясню примером.

    Рассматриваем мир в 2D, без учёта высоты y.
    Допустим, карта имеет координаты min (x = -4789, z = -2050); max (x = 3765, z = 1023).
    Плоскость мира делится на чанки блоков, размером по 16×16 блоков.
    Блок с координатой (0; 0) находится в чанке с координатой (0; 0) и имеет координату внутри этого чанка (0; 0).
    Блок с координатой (16; 15) находится в чанке с координатой (1; 0) и имеет координату внутри чанка (0; 15).
    Имея только координаты блока bx и bz мы можем найти координаты чанка cx и cz и координаты блока внутри чанка bcx и bcz (я буду писать формулы только для x, т.к. для z они отличаются только буквой z):
    cx = bx / 16 (целочисленное деление), bcx = bx % 16 (остаток от целочисленного деления).
    Обратно, если мы знаем координату чанка и координату блока внутри чанка, мы можем найти абсолютное положение блока в мире: bx = cx * 16 + bcx.
    Интереснее с отрицательной стороны координаты: если по формуле выше получается bcx < 0, то нужно сделать { bcx += 16; cx -= 1; }, чтобы привести координату блока в чанке в допустимые пределы [0; 15].

    Найдём границы условного мира в чанках. Сперва для отрицательного угла:
    cx1 = -4789 / 16 = -299; bcx = -4789 % 16 = -5.
    Применим фикс: cx1 = -300, bcx = 11.
    Аналогично находим для координаты z: cz1 = -129; bcz1 = 14.
    Для положительного угла: cx2 = 235; cz2 = 63. Я опускаю координаты блоков, так как они дальше никуда не сдались.
    Помним, что сервер не умеет работать с неполными чанками.
    Наш мир в чанках имеет следующие размеры: min (-300; -129); max (235; 63) — это то, что мы искали.
    Если интересна, то вот площадь мира в чанках: (235 - (-300) + 1) × (63 - (-129) + 1) = 103 448 чанка.

    Код:
    // Исходные данные: координаты угловых блоков мира
    void aaa(long minX, long minZ, long maxX, long maxZ) {
        // Вычисление границ мира в чанках
        long minCX = minX / 16;
        long minCZ = minZ / 16;
        long maxCX = maxX / 16;
        long maxCZ = maxZ / 16;
        if(minX % 16 < 0)
            minCX -= 1;
        if(minZ % 16 < 0)
            minCZ -= 1;
        // Дальше можно итерировать по ним
        for(long CZ = minCZ; CZ <= maxCZ; CZ++)
            for(long CX = minCX; CX <= maxCX; CX++)
            {
                // CX и CZ -- координата очередного чанка, принадлежащего имеющейся карте.
                // Надо их все запомнить куда-то для последующей обработки.
            }
    }
     
    Последнее редактирование: 29 июн 2016

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