Search in sources :

Example 1 with Schematic

use of org.spongepowered.api.world.schematic.Schematic in project SpongeCommon by SpongePowered.

the class SchematicTranslator method translate.

@Override
public Schematic translate(DataView view) throws InvalidDataException {
    int version = view.getInt(DataQueries.Schematic.VERSION).get();
    // TODO version conversions
    if (version != VERSION) {
        throw new InvalidDataException(String.format("Unknown schematic version %d (current version is %d)", version, VERSION));
    }
    DataView metadata = view.getView(DataQueries.Schematic.METADATA).orElse(null);
    if (metadata != null) {
        Optional<DataView> dot_data = metadata.getView(DataQuery.of("."));
        if (dot_data.isPresent()) {
            DataView data = dot_data.get();
            for (DataQuery key : data.getKeys(false)) {
                if (!metadata.contains(key)) {
                    metadata.set(key, data.get(key).get());
                }
            }
        }
    }
    // TODO error handling for these optionals
    int width = view.getShort(DataQueries.Schematic.WIDTH).get();
    int height = view.getShort(DataQueries.Schematic.HEIGHT).get();
    int length = view.getShort(DataQueries.Schematic.LENGTH).get();
    if (width > MAX_SIZE || height > MAX_SIZE || length > MAX_SIZE) {
        throw new InvalidDataException(String.format("Schematic is larger than maximum allowable size (found: (%d, %d, %d) max: (%d, %<d, %<d)", width, height, length, MAX_SIZE));
    }
    int[] offset = (int[]) view.get(DataQueries.Schematic.OFFSET).orElse(null);
    if (offset == null) {
        offset = new int[3];
    }
    if (offset.length != 3) {
        throw new InvalidDataException("Schematic offset was not of length 3");
    }
    BlockPalette palette;
    Optional<DataView> paletteData = view.getView(DataQueries.Schematic.PALETTE);
    int palette_max = view.getInt(DataQueries.Schematic.PALETTE_MAX).orElse(0xFFFF);
    if (paletteData.isPresent()) {
        // If we had a default palette_max we don't want to allocate all
        // that space for nothing so we use a sensible default instead
        palette = new BimapPalette(palette_max != 0xFFFF ? palette_max : 64);
        DataView paletteMap = paletteData.get();
        Set<DataQuery> paletteKeys = paletteMap.getKeys(false);
        for (DataQuery key : paletteKeys) {
            BlockState state = Sponge.getRegistry().getType(BlockState.class, key.getParts().get(0)).get();
            ((BimapPalette) palette).assign(state, paletteMap.getInt(key).get());
        }
    } else {
        palette = GlobalPalette.instance;
    }
    MutableBlockVolume buffer = new ArrayMutableBlockBuffer(palette, new Vector3i(-offset[0], -offset[1], -offset[2]), new Vector3i(width, height, length));
    byte[] blockdata = (byte[]) view.get(DataQueries.Schematic.BLOCK_DATA).get();
    int index = 0;
    int i = 0;
    int value = 0;
    int varint_length = 0;
    while (i < blockdata.length) {
        value = 0;
        varint_length = 0;
        while (true) {
            value |= (blockdata[i] & 127) << (varint_length++ * 7);
            if (varint_length > 5) {
                throw new RuntimeException("VarInt too big (probably corrupted data)");
            }
            if ((blockdata[i] & 128) != 128) {
                i++;
                break;
            }
            i++;
        }
        // index = (y * length + z) * width + x
        int y = index / (width * length);
        int z = (index % (width * length)) / width;
        int x = (index % (width * length)) % width;
        BlockState state = palette.get(value).get();
        buffer.setBlock(x - offset[0], y - offset[1], z - offset[2], state);
        index++;
    }
    Map<Vector3i, TileEntityArchetype> tiles = Maps.newHashMap();
    List<DataView> tiledata = view.getViewList(DataQueries.Schematic.TILEENTITY_DATA).orElse(null);
    if (tiledata != null) {
        for (DataView tile : tiledata) {
            int[] pos = (int[]) tile.get(DataQueries.Schematic.TILEENTITY_POS).get();
            if (offset.length != 3) {
                throw new InvalidDataException("Schematic tileentity pos was not of length 3");
            }
            TileEntityType type = TileEntityTypeRegistryModule.getInstance().getForClass(TileEntity.REGISTRY.getObject(new ResourceLocation(tile.getString(DataQuery.of("id")).get())));
            TileEntityArchetype archetype = new SpongeTileEntityArchetypeBuilder().state(buffer.getBlock(pos[0] - offset[0], pos[1] - offset[1], pos[2] - offset[2])).tileData(tile).tile(type).build();
            tiles.put(new Vector3i(pos[0] - offset[0], pos[1] - offset[1], pos[2] - offset[2]), archetype);
        }
    }
    Schematic schematic = new SpongeSchematic(buffer, tiles, metadata);
    return schematic;
}
Also used : BlockPalette(org.spongepowered.api.world.schematic.BlockPalette) MutableBlockVolume(org.spongepowered.api.world.extent.MutableBlockVolume) BimapPalette(org.spongepowered.common.world.schematic.BimapPalette) ArrayMutableBlockBuffer(org.spongepowered.common.util.gen.ArrayMutableBlockBuffer) SpongeTileEntityArchetypeBuilder(org.spongepowered.common.block.SpongeTileEntityArchetypeBuilder) DataView(org.spongepowered.api.data.DataView) SpongeSchematic(org.spongepowered.common.world.schematic.SpongeSchematic) BlockState(org.spongepowered.api.block.BlockState) TileEntityType(org.spongepowered.api.block.tileentity.TileEntityType) ResourceLocation(net.minecraft.util.ResourceLocation) InvalidDataException(org.spongepowered.api.data.persistence.InvalidDataException) Vector3i(com.flowpowered.math.vector.Vector3i) DataQuery(org.spongepowered.api.data.DataQuery) TileEntityArchetype(org.spongepowered.api.block.tileentity.TileEntityArchetype) Schematic(org.spongepowered.api.world.schematic.Schematic) SpongeSchematic(org.spongepowered.common.world.schematic.SpongeSchematic)

Example 2 with Schematic

use of org.spongepowered.api.world.schematic.Schematic in project SpongeCommon by SpongePowered.

the class CopyPasta method onGamePreInitialization.

@Listener
public void onGamePreInitialization(GamePreInitializationEvent event) {
    this.schematicsDir = new File(this.config, "schematics");
    this.schematicsDir.mkdirs();
    this.logger.info("Saving schematics to " + this.schematicsDir.getAbsolutePath());
    Sponge.getCommandManager().register(this, CommandSpec.builder().description(Text.of("Copies a region of the world to your clipboard")).permission(PLUGIN_ID + ".command.copy").executor((src, args) -> {
        if (!(src instanceof Player)) {
            src.sendMessage(Text.of(TextColors.RED, "Player only."));
            return CommandResult.success();
        }
        Player player = (Player) src;
        PlayerData data = get(player);
        if (data.getPos1() == null || data.getPos2() == null) {
            player.sendMessage(Text.of(TextColors.RED, "You must set both positions before copying"));
            return CommandResult.success();
        }
        Vector3i min = data.getPos1().min(data.getPos2());
        Vector3i max = data.getPos1().max(data.getPos2());
        ArchetypeVolume volume = player.getWorld().createArchetypeVolume(min, max, player.getLocation().getPosition().toInt());
        data.setClipboard(volume);
        player.sendMessage(Text.of(TextColors.GREEN, "Saved to clipboard."));
        return CommandResult.success();
    }).build(), "copy");
    Sponge.getCommandManager().register(this, CommandSpec.builder().description(Text.of("Pastes your clipboard at your current position")).permission(PLUGIN_ID + ".command.paste").executor((src, args) -> {
        if (!(src instanceof Player)) {
            src.sendMessage(Text.of(TextColors.RED, "Player only."));
            return CommandResult.success();
        }
        Player player = (Player) src;
        PlayerData data = get(player);
        ArchetypeVolume volume = data.getClipboard();
        if (volume == null) {
            player.sendMessage(Text.of(TextColors.RED, "You must copy something before pasting"));
            return CommandResult.success();
        }
        Sponge.getCauseStackManager().pushCause(this);
        volume.apply(player.getLocation(), BlockChangeFlags.ALL);
        Sponge.getCauseStackManager().popCause();
        player.sendMessage(Text.of(TextColors.GREEN, "Pasted clipboard into world."));
        return CommandResult.success();
    }).build(), "paste");
    Sponge.getCommandManager().register(this, CommandSpec.builder().description(Text.of("Saves your clipboard to disk")).permission(PLUGIN_ID + ".command.save").arguments(seq(string(Text.of("format")), string(Text.of("name")))).executor((src, args) -> {
        if (!(src instanceof Player)) {
            src.sendMessage(Text.of(TextColors.RED, "Player only."));
            return CommandResult.success();
        }
        String format = args.getOne("format").get().toString();
        String name = args.getOne("name").get().toString();
        Player player = (Player) src;
        PlayerData data = get(player);
        ArchetypeVolume volume = data.getClipboard();
        if (volume == null) {
            player.sendMessage(Text.of(TextColors.RED, "You must copy something before saving"));
            return CommandResult.success();
        }
        if (!"legacy".equalsIgnoreCase(format) && !"sponge".equalsIgnoreCase(format)) {
            player.sendMessage(Text.of(TextColors.RED, "Unsupported schematic format, supported formats are [legacy, sponge]"));
            return CommandResult.success();
        }
        Schematic schematic = Schematic.builder().volume(data.getClipboard()).metaValue(Schematic.METADATA_AUTHOR, player.getName()).metaValue(Schematic.METADATA_NAME, name).paletteType(BlockPaletteTypes.LOCAL).build();
        DataContainer schematicData = null;
        if ("legacy".equalsIgnoreCase(format)) {
            schematicData = DataTranslators.LEGACY_SCHEMATIC.translate(schematic);
        } else if ("sponge".equalsIgnoreCase(format)) {
            schematicData = DataTranslators.SCHEMATIC.translate(schematic);
        }
        File outputFile = new File(this.schematicsDir, name + ".schematic");
        try {
            DataFormats.NBT.writeTo(new GZIPOutputStream(new FileOutputStream(outputFile)), schematicData);
            player.sendMessage(Text.of(TextColors.GREEN, "Saved schematic to " + outputFile.getAbsolutePath()));
        } catch (Exception e) {
            e.printStackTrace();
            player.sendMessage(Text.of(TextColors.DARK_RED, "Error saving schematic: " + e.getMessage()));
            return CommandResult.success();
        }
        return CommandResult.success();
    }).build(), "save");
    Sponge.getCommandManager().register(this, CommandSpec.builder().description(Text.of("Loads a schematic from disk to your clipboard")).permission(PLUGIN_ID + ".command.load").arguments(seq(string(Text.of("format")), string(Text.of("name")))).executor((src, args) -> {
        if (!(src instanceof Player)) {
            src.sendMessage(Text.of(TextColors.RED, "Player only."));
            return CommandResult.success();
        }
        String format = args.getOne("format").get().toString();
        String name = args.getOne("name").get().toString();
        Player player = (Player) src;
        PlayerData data = get(player);
        if (!"legacy".equalsIgnoreCase(format) && !"sponge".equalsIgnoreCase(format)) {
            player.sendMessage(Text.of(TextColors.RED, "Unsupported schematic format, supported formats are [legacy, sponge]"));
            return CommandResult.success();
        }
        File inputFile = new File(this.schematicsDir, name + ".schematic");
        if (!inputFile.exists()) {
            player.sendMessage(Text.of(TextColors.RED, "Schematic at " + inputFile.getAbsolutePath() + " not found."));
            return CommandResult.success();
        }
        DataContainer schematicData = null;
        try {
            schematicData = DataFormats.NBT.readFrom(new GZIPInputStream(new FileInputStream(inputFile)));
        } catch (Exception e) {
            e.printStackTrace();
            player.sendMessage(Text.of(TextColors.DARK_RED, "Error loading schematic: " + e.getMessage()));
            return CommandResult.success();
        }
        Schematic schematic = null;
        if ("legacy".equalsIgnoreCase(format)) {
            schematic = DataTranslators.LEGACY_SCHEMATIC.translate(schematicData);
        } else if ("sponge".equalsIgnoreCase(format)) {
            schematic = DataTranslators.SCHEMATIC.translate(schematicData);
        }
        player.sendMessage(Text.of(TextColors.GREEN, "Loaded schematic from " + inputFile.getAbsolutePath()));
        data.setClipboard(schematic);
        return CommandResult.success();
    }).build(), "load");
}
Also used : Player(org.spongepowered.api.entity.living.player.Player) FileInputStream(java.io.FileInputStream) ArchetypeVolume(org.spongepowered.api.world.extent.ArchetypeVolume) GZIPInputStream(java.util.zip.GZIPInputStream) DataContainer(org.spongepowered.api.data.DataContainer) GZIPOutputStream(java.util.zip.GZIPOutputStream) FileOutputStream(java.io.FileOutputStream) Vector3i(com.flowpowered.math.vector.Vector3i) File(java.io.File) Schematic(org.spongepowered.api.world.schematic.Schematic) Listener(org.spongepowered.api.event.Listener)

Aggregations

Vector3i (com.flowpowered.math.vector.Vector3i)2 Schematic (org.spongepowered.api.world.schematic.Schematic)2 File (java.io.File)1 FileInputStream (java.io.FileInputStream)1 FileOutputStream (java.io.FileOutputStream)1 GZIPInputStream (java.util.zip.GZIPInputStream)1 GZIPOutputStream (java.util.zip.GZIPOutputStream)1 ResourceLocation (net.minecraft.util.ResourceLocation)1 BlockState (org.spongepowered.api.block.BlockState)1 TileEntityArchetype (org.spongepowered.api.block.tileentity.TileEntityArchetype)1 TileEntityType (org.spongepowered.api.block.tileentity.TileEntityType)1 DataContainer (org.spongepowered.api.data.DataContainer)1 DataQuery (org.spongepowered.api.data.DataQuery)1 DataView (org.spongepowered.api.data.DataView)1 InvalidDataException (org.spongepowered.api.data.persistence.InvalidDataException)1 Player (org.spongepowered.api.entity.living.player.Player)1 Listener (org.spongepowered.api.event.Listener)1 ArchetypeVolume (org.spongepowered.api.world.extent.ArchetypeVolume)1 MutableBlockVolume (org.spongepowered.api.world.extent.MutableBlockVolume)1 BlockPalette (org.spongepowered.api.world.schematic.BlockPalette)1