Помогите как сохранить схематик?

  • Автор темы Автор темы InterVi
  • Дата начала Дата начала

InterVi

Старожил
Пользователь
Баллы
173
Имя в Minecraft
InterVi
Нужно сохранить регион из WG в схематик WE. Можно код для примера, пожалуйста. А то нифига не понятно, особенно что за size принимает CuboidClipboard и где его взять.
 
1. Находишь постройку.
2. Выделяешь топором или чем-то другим из WE.
3. Пишешь //copy
4. Пишешь //schematic save *Имя Схемы*
5. Чтобы вставить пишешь //schematic load *Имя Схемы*
 
1. Находишь постройку.
2. Выделяешь топором или чем-то другим из WE.
3. Пишешь //copy
4. Пишешь //schematic save *Имя Схемы*
5. Чтобы вставить пишешь //schematic load *Имя Схемы*
Это тут причем вообще? Я плагин пишу. Не понятно как мне в коде CuboidClipboard получить, взяв данные у ProtectedRegion в WorldGuard.
 
Взял из WorldEdit 6.1
Код:
  public void save(CuboidClipboard clipboard, File file)
    throws IOException, DataException
  {
    int width = clipboard.getWidth();
    int height = clipboard.getHeight();
    int length = clipboard.getLength();
    if (width > 65535) {
      throw new DataException("Width of region too large for a .schematic");
    }
    if (height > 65535) {
      throw new DataException("Height of region too large for a .schematic");
    }
    if (length > 65535) {
      throw new DataException("Length of region too large for a .schematic");
    }
    HashMap<String, Tag> schematic = new HashMap();
    schematic.put("Width", new ShortTag((short)width));
    schematic.put("Length", new ShortTag((short)length));
    schematic.put("Height", new ShortTag((short)height));
    schematic.put("Materials", new StringTag("Alpha"));
    schematic.put("WEOriginX", new IntTag(clipboard.getOrigin().getBlockX()));
    schematic.put("WEOriginY", new IntTag(clipboard.getOrigin().getBlockY()));
    schematic.put("WEOriginZ", new IntTag(clipboard.getOrigin().getBlockZ()));
    schematic.put("WEOffsetX", new IntTag(clipboard.getOffset().getBlockX()));
    schematic.put("WEOffsetY", new IntTag(clipboard.getOffset().getBlockY()));
    schematic.put("WEOffsetZ", new IntTag(clipboard.getOffset().getBlockZ()));
  
    byte[] blocks = new byte[width * height * length];
    byte[] addBlocks = null;
    byte[] blockData = new byte[width * height * length];
    ArrayList<Tag> tileEntities = new ArrayList();
    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));
          if (block.getType() > 255)
          {
            if (addBlocks == null) {
              addBlocks = new byte[(blocks.length >> 1) + 1];
            }
            addBlocks[(index >> 1)] = ((byte)((index & 0x1) == 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());
        
          CompoundTag rawTag = block.getNbtData();
          if (rawTag != null)
          {
            Map<String, Tag> values = new HashMap();
            for (Map.Entry<String, Tag> entry : rawTag.getValue().entrySet()) {
              values.put(entry.getKey(), entry.getValue());
            }
            values.put("id", new StringTag(block.getNbtId()));
            values.put("x", new IntTag(x));
            values.put("y", new IntTag(y));
            values.put("z", new IntTag(z));
          
            CompoundTag tileEntityTag = new CompoundTag(values);
            tileEntities.add(tileEntityTag);
          }
        }
      }
    }
    schematic.put("Blocks", new ByteArrayTag(blocks));
    schematic.put("Data", new ByteArrayTag(blockData));
    schematic.put("Entities", new ListTag(CompoundTag.class, new ArrayList()));
    schematic.put("TileEntities", new ListTag(CompoundTag.class, tileEntities));
    if (addBlocks != null) {
      schematic.put("AddBlocks", new ByteArrayTag(addBlocks));
    }
    CompoundTag schematicTag = new CompoundTag(schematic);
    NBTOutputStream stream = new NBTOutputStream(new GZIPOutputStream(new FileOutputStream(file)));
    stream.writeNamedTag("Schematic", schematicTag);
    stream.close();
  }
 
Последнее редактирование:
Взял из WorldEdit 6.1
Код:
  public CuboidClipboard load(File file)
    throws IOException, DataException
  {
    return load(new FileInputStream(file));
  }

  public void save(CuboidClipboard clipboard, File file)
    throws IOException, DataException
  {
    int width = clipboard.getWidth();
    int height = clipboard.getHeight();
    int length = clipboard.getLength();
    if (width > 65535) {
      throw new DataException("Width of region too large for a .schematic");
    }
    if (height > 65535) {
      throw new DataException("Height of region too large for a .schematic");
    }
    if (length > 65535) {
      throw new DataException("Length of region too large for a .schematic");
    }
    HashMap<String, Tag> schematic = new HashMap();
    schematic.put("Width", new ShortTag((short)width));
    schematic.put("Length", new ShortTag((short)length));
    schematic.put("Height", new ShortTag((short)height));
    schematic.put("Materials", new StringTag("Alpha"));
    schematic.put("WEOriginX", new IntTag(clipboard.getOrigin().getBlockX()));
    schematic.put("WEOriginY", new IntTag(clipboard.getOrigin().getBlockY()));
    schematic.put("WEOriginZ", new IntTag(clipboard.getOrigin().getBlockZ()));
    schematic.put("WEOffsetX", new IntTag(clipboard.getOffset().getBlockX()));
    schematic.put("WEOffsetY", new IntTag(clipboard.getOffset().getBlockY()));
    schematic.put("WEOffsetZ", new IntTag(clipboard.getOffset().getBlockZ()));
  
    byte[] blocks = new byte[width * height * length];
    byte[] addBlocks = null;
    byte[] blockData = new byte[width * height * length];
    ArrayList<Tag> tileEntities = new ArrayList();
    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));
          if (block.getType() > 255)
          {
            if (addBlocks == null) {
              addBlocks = new byte[(blocks.length >> 1) + 1];
            }
            addBlocks[(index >> 1)] = ((byte)((index & 0x1) == 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());
        
          CompoundTag rawTag = block.getNbtData();
          if (rawTag != null)
          {
            Map<String, Tag> values = new HashMap();
            for (Map.Entry<String, Tag> entry : rawTag.getValue().entrySet()) {
              values.put(entry.getKey(), entry.getValue());
            }
            values.put("id", new StringTag(block.getNbtId()));
            values.put("x", new IntTag(x));
            values.put("y", new IntTag(y));
            values.put("z", new IntTag(z));
          
            CompoundTag tileEntityTag = new CompoundTag(values);
            tileEntities.add(tileEntityTag);
          }
        }
      }
    }
    schematic.put("Blocks", new ByteArrayTag(blocks));
    schematic.put("Data", new ByteArrayTag(blockData));
    schematic.put("Entities", new ListTag(CompoundTag.class, new ArrayList()));
    schematic.put("TileEntities", new ListTag(CompoundTag.class, tileEntities));
    if (addBlocks != null) {
      schematic.put("AddBlocks", new ByteArrayTag(addBlocks));
    }
    CompoundTag schematicTag = new CompoundTag(schematic);
    NBTOutputStream stream = new NBTOutputStream(new GZIPOutputStream(new FileOutputStream(file)));
    stream.writeNamedTag("Schematic", schematicTag);
    stream.close();
  }
А про CuboidClipboard можно подробнее, как его получить? Его не от игрока взять нужно, а от региона WorldGuard. Нигде не нашел как можно его собрать искусственно.
 
Короче, вот метод, который выделяет заданный регион
Код:
protected static void setPlayerSelection(Player player, ProtectedRegion region) throws CommandException {
WorldEditPlugin worldEdit = WorldGuardPlugin.inst().getWorldEdit();
World world = player.getWorld();
// Set selection
if (region instanceof ProtectedCuboidRegion) {
ProtectedCuboidRegion cuboid = (ProtectedCuboidRegion) region;
Vector pt1 = cuboid.getMinimumPoint();
Vector pt2 = cuboid.getMaximumPoint();
CuboidSelection selection = new CuboidSelection(world, pt1, pt2);
worldEdit.setSelection(player, selection);
player.sendMessage(ChatColor.YELLOW + "Region selected as a cuboid.");
} else if (region instanceof ProtectedPolygonalRegion) {
ProtectedPolygonalRegion poly2d = (ProtectedPolygonalRegion) region;
Polygonal2DSelection selection = new Polygonal2DSelection(
world, poly2d.getPoints(),
poly2d.getMinimumPoint().getBlockY(),
poly2d.getMaximumPoint().getBlockY() );
worldEdit.setSelection(player, selection);
player.sendMessage(ChatColor.YELLOW + "Region selected as a polygon.");
} else if (region instanceof GlobalProtectedRegion) {
throw new CommandException(
"Can't select global regions! " +
"That would cover the entire world.");
} else {
throw new CommandException("Unknown region type: " +
region.getClass().getCanonicalName());
}
}
Дальше сам сможешь?
Нужно будет получить то, что "выделил" игрок
 
Короче, вот метод, который выделяет заданный регион
Код:
protected static void setPlayerSelection(Player player, ProtectedRegion region) throws CommandException {
WorldEditPlugin worldEdit = WorldGuardPlugin.inst().getWorldEdit();
World world = player.getWorld();
// Set selection
if (region instanceof ProtectedCuboidRegion) {
ProtectedCuboidRegion cuboid = (ProtectedCuboidRegion) region;
Vector pt1 = cuboid.getMinimumPoint();
Vector pt2 = cuboid.getMaximumPoint();
CuboidSelection selection = new CuboidSelection(world, pt1, pt2);
worldEdit.setSelection(player, selection);
player.sendMessage(ChatColor.YELLOW + "Region selected as a cuboid.");
} else if (region instanceof ProtectedPolygonalRegion) {
ProtectedPolygonalRegion poly2d = (ProtectedPolygonalRegion) region;
Polygonal2DSelection selection = new Polygonal2DSelection(
world, poly2d.getPoints(),
poly2d.getMinimumPoint().getBlockY(),
poly2d.getMaximumPoint().getBlockY() );
worldEdit.setSelection(player, selection);
player.sendMessage(ChatColor.YELLOW + "Region selected as a polygon.");
} else if (region instanceof GlobalProtectedRegion) {
throw new CommandException(
"Can't select global regions! " +
"That would cover the entire world.");
} else {
throw new CommandException("Unknown region type: " +
region.getClass().getCanonicalName());
}
}
Дальше сам сможешь?
Нужно будет получить то, что "выделил" игрок
Ну вроде понятно, придется все-таки возится с игроком. Спасибо.
 
Тоже была необходимость сохранить схематик в файл без участия игрока. В итоге, удалось собрать только вот такой вот велосипед:

Код:
RegionManager rg = WGBukkit.getRegionManager( world );
Map< String, ProtectedRegion > regions = rg.getRegions();

saveToSchematic( protectedregion );
Код:
    private void saveToSchematic( ProtectedRegion region) {   
        Vector minimumPoint = region.getMinimumPoint();
        Vector maximumPoint = region.getMaximumPoint();

        Vector regionSize = maximumPoint.subtract(minimumPoint).add(1, 1, 1);
        int regionVolume = regionSize.getBlockX() * regionSize.getBlockY() * regionSize.getBlockZ();
       
        File schematicsFolder = new File(plugin.getDataFolder(), "hash/schematics/");
        File schematicFile = new File(schematicsFolder, worldName + File.separator + region.getId() + ".schematic");
        schematicFile.getParentFile().mkdirs();
    
        CuboidClipboard clipboard = new CuboidClipboard(regionSize, minimumPoint);
        EditSession editSession = new EditSession(new BukkitWorld(world), regionVolume);
        clipboard.copy(editSession);
           
        try {
            SchematicFormat.MCEDIT.save( clipboard, schematicFile );
            //format.save(clipboard, schematicFile);
        } catch ( Exception e ) {
            e.printStackTrace();
        }
    }

Только есть один минус данного "костыля" - он не сохраняет NBT.
 
Тоже была необходимость сохранить схематик в файл без участия игрока. В итоге, удалось собрать только вот такой вот велосипед:

Код:
RegionManager rg = WGBukkit.getRegionManager( world );
Map< String, ProtectedRegion > regions = rg.getRegions();

saveToSchematic( protectedregion );
Код:
    private void saveToSchematic( ProtectedRegion region) {  
        Vector minimumPoint = region.getMinimumPoint();
        Vector maximumPoint = region.getMaximumPoint();

        Vector regionSize = maximumPoint.subtract(minimumPoint).add(1, 1, 1);
        int regionVolume = regionSize.getBlockX() * regionSize.getBlockY() * regionSize.getBlockZ();
      
        File schematicsFolder = new File(plugin.getDataFolder(), "hash/schematics/");
        File schematicFile = new File(schematicsFolder, worldName + File.separator + region.getId() + ".schematic");
        schematicFile.getParentFile().mkdirs();
   
        CuboidClipboard clipboard = new CuboidClipboard(regionSize, minimumPoint);
        EditSession editSession = new EditSession(new BukkitWorld(world), regionVolume);
        clipboard.copy(editSession);
          
        try {
            SchematicFormat.MCEDIT.save( clipboard, schematicFile );
            //format.save(clipboard, schematicFile);
        } catch ( Exception e ) {
            e.printStackTrace();
        }
    }

Только есть один минус данного "костыля" - он не сохраняет NBT.
Сохраняет при наличии правильной версии WE на сервере.
 
спасибо, займусь проверкой как будет время

из последних?
Нет, как было выявлено опытным путём, только при наличии конкретной версии WE под конкретную версию Bukkit.
К счастью, в WE/WG 6+ добавили, так называемые, "адаптеры" в виде Forge-мода. В итоге, проблема решается установкой нужной версии мода-адаптера. Минусом является только то, что адаптеры будут только под Bukkit для 1.7.* и старше.
 
Не схематик, а чертёж объекта!
 
Нет, как было выявлено опытным путём, только при наличии конкретной версии WE под конкретную версию Bukkit.
К счастью, в WE/WG 6+ добавили, так называемые, "адаптеры" в виде Forge-мода. В итоге, проблема решается установкой нужной версии мода-адаптера. Минусом является только то, что адаптеры будут только под Bukkit для 1.7.* и старше.
WE очень долгое время уже поддерживает блоки из модов, есть у него такая вещь как NMS.
 
WE очень долгое время уже поддерживает блоки из модов, есть у него такая вещь как NMS.
Да, но в последнее время он не умеет переносить тайлы, для этого вместе с плагином нужно устанавливать мод
Адаптер на 1.6.4 существует, я видел только его, когда искал на 1.7.10 и не находил, а уже только потом нашёл где скачать под 1.7.10.
 
У кого-то получилось сохранять tileEntities? Мои велосипеды так же их не сохраняют, хотя нативный WE сохраняет. Forge-версия установлена.
 
У кого-то получилось сохранять tileEntities? Мои велосипеды так же их не сохраняют, хотя нативный WE сохраняет. Forge-версия установлена.
Потом ещё намучаешься их обратно вставлять.
Лучше режь чанки.

А если по сути, то надо выгрузить нбт тэг из тайла, сериализовать его в поток, а при вставке сделать обратный трюк. Но множетсво тайлов, особенно из модов крайне плохо реагируют на загрузку данных из тэга после загрузки чанка.
 
Назад
Верх