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

Помогите Сохранение части мира в схематику

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

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

    serega6531 Старожил Девелопер Пользователь

    Баллы:
    173
    Skype:
    shkurovs
  2. kirill2011s

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

    Баллы:
    103
    Я дал прямую ссылку на код github'а.
     
  3. Автор темы
    serega6531

    serega6531 Старожил Девелопер Пользователь

    Баллы:
    173
    Skype:
    shkurovs
    Мы говорим о разных вещах. Я дал ссылку на статью с примерами кода с комментариями, а вы мне дали страницу кода, которую я уже видел и не понял.
     
  4. kirill2011s

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

    Баллы:
    103
    Код:
    public void save(CuboidClipboard clipboard, File file) throws IOException, DataException {
            int width = clipboard.getWidth();
            int height = clipboard.getHeight();
            int length = clipboard.getLength();
    
            if (width > MAX_SIZE) {
                throw new DataException("Width of region too large for a .schematic");
            }
            if (height > MAX_SIZE) {
                throw new DataException("Height of region too large for a .schematic");
            }
            if (length > MAX_SIZE) {
                throw new DataException("Length of region too large for a .schematic");
            }
    
            HashMap<String, Tag> schematic = new HashMap<String, Tag>();
            schematic.put("Width", new ShortTag("Width", (short) width));
            schematic.put("Length", new ShortTag("Length", (short) length));
            schematic.put("Height", new ShortTag("Height", (short) height));
            schematic.put("Materials", new StringTag("Materials", "Alpha"));
            schematic.put("WEOriginX", new IntTag("WEOriginX", clipboard.getOrigin().getBlockX()));
            schematic.put("WEOriginY", new IntTag("WEOriginY", clipboard.getOrigin().getBlockY()));
            schematic.put("WEOriginZ", new IntTag("WEOriginZ", clipboard.getOrigin().getBlockZ()));
            schematic.put("WEOffsetX", new IntTag("WEOffsetX", clipboard.getOffset().getBlockX()));
            schematic.put("WEOffsetY", new IntTag("WEOffsetY", clipboard.getOffset().getBlockY()));
            schematic.put("WEOffsetZ", new IntTag("WEOffsetZ", clipboard.getOffset().getBlockZ()));
    
            // Copy
            byte[] blocks = new byte[width * height * length];
            byte[] addBlocks = null;
            byte[] blockData = new byte[width * height * length];
            ArrayList<Tag> tileEntities = new ArrayList<Tag>();
    
            for (int x = 0; x < width; ++x) {
                for (int y = 0; y < height; ++y) {
                    for (int z = 0; z < length; ++z) {
                        int index = y * width * length + z * width + x;
                        BaseBlock block = clipboard.getPoint(new BlockVector(x, y, z));
    
                        // Save 4096 IDs in an AddBlocks section
                        if (block.getType() > 255) {
                            if (addBlocks == null) { // Lazily create section
                                addBlocks = new byte[(blocks.length >> 1) + 1];
                            }
    
                            addBlocks[index >> 1] = (byte) (((index & 1) == 0) ?
                                    addBlocks[index >> 1] & 0xF0 | (block.getType() >> 8) & 0xF
                                    : addBlocks[index >> 1] & 0xF | ((block.getType() >> 8) & 0xF) << 4);
                        }
    
                        blocks[index] = (byte) block.getType();
                        blockData[index] = (byte) block.getData();
    
                        // Store TileEntity data
                        if (block instanceof TileEntityBlock) {
                            TileEntityBlock tileEntityBlock = block;
    
                            // Get the list of key/values from the block
                            CompoundTag rawTag = tileEntityBlock.getNbtData();
                            if (rawTag != null) {
                                Map<String, Tag> values = new HashMap<String, Tag>();
                                for (Entry<String, Tag> entry : rawTag.getValue().entrySet()) {
                                    values.put(entry.getKey(), entry.getValue());
                                }
                               
                                values.put("id", new StringTag("id", tileEntityBlock.getNbtId()));
                                values.put("x", new IntTag("x", x));
                                values.put("y", new IntTag("y", y));
                                values.put("z", new IntTag("z", z));
                               
                                CompoundTag tileEntityTag = new CompoundTag("TileEntity", values);
                                tileEntities.add(tileEntityTag);
                            }
                        }
                    }
                }
            }
    
            schematic.put("Blocks", new ByteArrayTag("Blocks", blocks));
            schematic.put("Data", new ByteArrayTag("Data", blockData));
            schematic.put("Entities", new ListTag("Entities", CompoundTag.class, new ArrayList<Tag>()));
            schematic.put("TileEntities", new ListTag("TileEntities", CompoundTag.class, tileEntities));
            if (addBlocks != null) {
                schematic.put("AddBlocks", new ByteArrayTag("AddBlocks", addBlocks));
            }
    
            // Build and output
            CompoundTag schematicTag = new CompoundTag("Schematic", schematic);
            NBTOutputStream stream = new NBTOutputStream(new FileOutputStream(file));
            stream.writeTag(schematicTag);
            stream.close();
        }
    Конкретно вывод после // Build and output.
     
  5. Автор темы
    serega6531

    serega6531 Старожил Девелопер Пользователь

    Баллы:
    173
    Skype:
    shkurovs
    А вот это уже что-то. Попробую.
     
  6. kirill2011s

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

    Баллы:
    103
    Хех, больше чем уверен, что вы запутались, потому что класс SchematicFormat абстрактный, и не понятно куда от него идти)
     
  7. Автор темы
    serega6531

    serega6531 Старожил Девелопер Пользователь

    Баллы:
    173
    Skype:
    shkurovs
    Я вот такое наугад сделал:
    Код:
        public static void save(Location from, Location to, File file) throws IOException, DataException{
            Location ll = from.subtract(to);
            Vector lv = new Vector(ll.getBlockX(), ll.getBlockY(), ll.getBlockZ());
            new CuboidClipboard(lv,
                    new Vector(from.getBlockX(), from.getBlockY(), from.getBlockZ()),
                    new Vector(to.getBlockX(), to.getBlockY(), to.getBlockZ()))
            .saveSchematic(file);
        }
    Размер схематики тот, но внутри ничего нет. Схематика пустая. from по всем параметрам больше to, если что.
    @kirill2011s, всё равно не понятно, что такое size, offset и origin.
     
  8. kirill2011s

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

    Баллы:
    103
    Где написаны size offset и origin? Чет не могу найти)
     
  9. Автор темы
    serega6531

    serega6531 Старожил Девелопер Пользователь

    Баллы:
    173
    Skype:
    shkurovs
    В конструкторе CuboidClipboard.
     
  10. fromgate

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

    Баллы:
    173
    Имя в Minecraft:
    fromgate
    Честно говоря я уже мало помню ;)
    Вообще же, насколько помню сотвторить CuboidClipboard должно быть не сложно. У меня правда была обратная операция - https://github.com/fromgate/ScLoad/blob/master/src/me/fromgate/scload/SLQueue.java я всё же загружал из файла и готовил очередь на установку блоков
     
  11. Автор темы
    serega6531

    serega6531 Старожил Девелопер Пользователь

    Баллы:
    173
    Skype:
    shkurovs
    Я смотрел ваши исходники, но мне не нужна загрузка. Сложность в том, что я не знаю, как делать CuboidClipboard. Что означают все эти size, offset и origin.
     
    Последнее редактирование: 8 июл 2014
  12. kirill2011s

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

    Баллы:
    103
    Вообщем, долго искал, и судя по этому:
    Код:
            Region region = session.getSelection(player.getWorld());
            Vector min = region.getMinimumPoint();
            Vector max = region.getMaximumPoint();
            Vector pos = session.getPlacementPosition(player);
    
            CuboidClipboard clipboard = new CuboidClipboard(
                    max.subtract(min).add(Vector.ONE),
                    min, min.subtract(pos));
    
    Третий тип конструктора, самое то. Ну в общем, дальше думаю разберетесь.
     
  13. Автор темы
    serega6531

    serega6531 Старожил Девелопер Пользователь

    Баллы:
    173
    Skype:
    shkurovs
    Спасибо за помощь.
    Вот ещё, а что означает pos?
     
  14. fromgate

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

    Баллы:
    173
    Имя в Minecraft:
    fromgate
    Судя по всему это позиция игрока относительно которой начинается формирование клипборда. Чтобы потом точно также вставлять.
     
  15. Автор темы
    serega6531

    serega6531 Старожил Девелопер Пользователь

    Баллы:
    173
    Skype:
    shkurovs
    Тогда буду использовать минимальную точку, но min.subtract(pos) - это будет 0?
     
  16. fromgate

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

    Баллы:
    173
    Имя в Minecraft:
    fromgate
    Ну а когда там отрицательные значения - Вас это не смущает? По идее должно быть всё нормально
     
  17. Автор темы
    serega6531

    serega6531 Старожил Девелопер Пользователь

    Баллы:
    173
    Skype:
    shkurovs
    Это относительный 0?
    Сделал вот так:
    Код:
            Location[] c = arena.getCorners();
            Vector min = vector(c[1]);
            Vector max = vector(c[0]);
            Vector offset = new Vector(0, 0, 0);
            try {
                SchematicFormat.MCEDIT.save(new CuboidClipboard(
                        max.subtract(min).add(Vector.ONE),
                        min, offset), new File(TheBridges.instance.getDataFolder(), "arena.schematic"));
            } catch (IOException | DataException e) {
                e.printStackTrace();
            }
    Но схематика создается в два раза больше, чем надо, и пустая.
    Изменил на
    new CuboidClipboard( max, min, new Vector(0,0,0))
    размер, вроде, нормальный, но схематика пустая.
     
    Последнее редактирование: 9 июл 2014
  18. Shevchik

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

    Баллы:
    173
    Имя в Minecraft:
    _Shevchik_
  19. Автор темы
    serega6531

    serega6531 Старожил Девелопер Пользователь

    Баллы:
    173
    Skype:
    shkurovs
    Спасибо, посмотрю.
    Я сделал вот такой класс:
    Код:
    public class Schematic {
      
        public static void save(File file, Location from, Location to){
            try {
                BukkitWorld bw = new BukkitWorld(from.getWorld());
                EditSession es = new EditSession(bw, Integer.MAX_VALUE);
                CuboidClipboard clipboard = new CuboidClipboard(
                    vector(to.subtract(from).add(1, 1, 1)),
                    vector(from),
                    vector(from.subtract(to))
                );
                Region region = new CuboidRegion(bw, vector(from), vector(to));
                es.setFastMode(true);
                clipboard.copy(es);
                LocalEntity[] entities = bw.getEntities(region);
                for (LocalEntity entity : entities) {
                    clipboard.storeEntity(entity);
                }
                SchematicFormat.MCEDIT.save(clipboard, file);
            } catch (IOException | DataException e) {
                e.printStackTrace();
            }
        }
      
        public static void loadAndPaste(File file, Location loc) throws IOException, DataException{
            final CuboidClipboard clipboard = SchematicFormat.MCEDIT.load(file);
          
            final Vector size = clipboard.getSize();
            final Vector origin = clipboard.getOrigin();
            for (int x = -16*3; x < size.getBlockX() + 16*3; x+=16) {
                for (int z = -16*3; z < size.getBlockZ() + 16*3; z+=16) {
                    loc.getWorld().getChunkAt(origin.getBlockX()+x, origin.getBlockZ()+z).load();
                }
            }
          
            EditSession es = new EditSession(new BukkitWorld(loc.getWorld()), Integer.MAX_VALUE);
            es.setFastMode(true);
            es.enableQueue();
            for (int x = 0; x < size.getBlockX(); ++x) {
                for (int y = 0; y < size.getBlockY(); ++y) {
                    for (int z = 0; z < size.getBlockZ(); ++z) {
                        Vector blockpos = new Vector(x, y, z);
                        final BaseBlock block = clipboard.getBlock(blockpos);
    
                        if (block == null) {
                            continue;
                        }
    
                        Bukkit.getScheduler().runTask(TheBridges.instance, new PasteRunnable(blockpos.add(origin), block, es));
                    }
                }
            }
            try {
                es.flushQueue();
            } catch (Throwable t) {
                t.printStackTrace();
            }
            try {
                clipboard.pasteEntities(origin);
            } catch (Throwable t) {
                t.printStackTrace();
            }
        }
      
        private static Vector vector(Location loc){
            return new Vector(loc.getX(), loc.getY(), loc.getX());
        }
      
    }
    
    class PasteRunnable implements Runnable {
      
        Vector pos;
        BaseBlock block;
        EditSession es;
      
        public PasteRunnable(Vector pos, BaseBlock block, EditSession es){
            this.pos = pos;
            this.block = block;
            this.es = es;
        }
    
        @Override
        public void run() {
            try {
                es.smartSetBlock(pos, block);
            } catch (Throwable t) {
                t.printStackTrace();
            }
        }
      
    }
    Он делает схематику, но не загружает её обратно. На карте ничего не меняется.
     

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