Search in sources :

Example 1 with BlockPalette

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

the class LegacySchematicTranslator method translate.

@Override
public Schematic translate(DataView view) throws InvalidDataException {
    // We default to sponge as the assumption should be that if this tag
    // (which is not in the sponge schematic specification) is not present
    // then it is more likely that its a sponge schematic than a legacy
    // schematic
    String materials = view.getString(DataQueries.Schematic.LEGACY_MATERIALS).orElse("Sponge");
    if ("Sponge".equalsIgnoreCase(materials)) {
        // not a legacy schematic use the new loader instead.
        return DataTranslators.SCHEMATIC.translate(view);
    } else if (!"Alpha".equalsIgnoreCase(materials)) {
        throw new InvalidDataException(String.format("Schematic specifies unknown materials %s", materials));
    }
    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 offsetX = view.getInt(DataQueries.Schematic.LEGACY_OFFSET_X).orElse(0);
    int offsetY = view.getInt(DataQueries.Schematic.LEGACY_OFFSET_Y).orElse(0);
    int offsetZ = view.getInt(DataQueries.Schematic.LEGACY_OFFSET_Z).orElse(0);
    BlockPalette palette = GlobalPalette.instance;
    ArrayMutableBlockBuffer buffer = new ArrayMutableBlockBuffer(new Vector3i(-offsetX, -offsetY, -offsetZ), new Vector3i(width, height, length));
    byte[] block_ids = (byte[]) view.get(DataQueries.Schematic.LEGACY_BLOCKS).get();
    byte[] block_data = (byte[]) view.get(DataQueries.Schematic.LEGACY_BLOCK_DATA).get();
    byte[] add_block = (byte[]) view.get(DataQueries.Schematic.LEGACY_ADD_BLOCKS).orElse(null);
    for (int x = 0; x < width; x++) {
        for (int y = 0; y < height; y++) {
            for (int z = 0; z < length; z++) {
                int index = (y * length + z) * width + x;
                final int default_state_id = block_ids[index];
                final int blockData = block_data[index] & 0xF;
                int palette_id = default_state_id << 4 | blockData;
                if (add_block != null) {
                    palette_id |= add_block[index] << 12;
                }
                Optional<BlockState> blockState = palette.get(palette_id);
                if (!blockState.isPresent()) {
                    // At the very least get the default state id
                    blockState = Optional.of((BlockState) Block.REGISTRY.getObjectById(default_state_id));
                }
                BlockState block = blockState.orElseGet(BlockTypes.COBBLESTONE::getDefaultState);
                buffer.setBlock(x - offsetX, y - offsetY, z - offsetZ, block);
            }
        }
    }
    Map<Vector3i, TileEntityArchetype> tiles = Maps.newHashMap();
    List<DataView> tiledata = view.getViewList(DataQueries.Schematic.LEGACY_TILEDATA).orElse(null);
    if (tiledata != null) {
        for (DataView tile : tiledata) {
            int x = tile.getInt(DataQueries.X_POS).get();
            int y = tile.getInt(DataQueries.Y_POS).get();
            int z = tile.getInt(DataQueries.Z_POS).get();
            final String tileType = tile.getString(TILE_ID).get();
            final ResourceLocation name = new ResourceLocation(tileType);
            TileEntityType type = TileEntityTypeRegistryModule.getInstance().getForClass(TileEntity.REGISTRY.getObject(name));
            final BlockState state = buffer.getBlock(x - offsetX, y - offsetY, z - offsetZ);
            // fixers.
            if (type != null && SpongeImplHooks.hasBlockTileEntity(((Block) state.getType()), BlockUtil.toNative(state))) {
                TileEntityArchetype archetype = new SpongeTileEntityArchetypeBuilder().state(state).tileData(tile).tile(type).build();
                tiles.put(new Vector3i(x - offsetX, y - offsetY, z - offsetZ), archetype);
            }
        }
    }
    SpongeSchematic schematic = new SpongeSchematic(buffer, tiles);
    return schematic;
}
Also used : BlockPalette(org.spongepowered.api.world.schematic.BlockPalette) 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) TileEntityArchetype(org.spongepowered.api.block.tileentity.TileEntityArchetype)

Example 2 with BlockPalette

use of org.spongepowered.api.world.schematic.BlockPalette 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 3 with BlockPalette

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

the class SchematicTranslator method addTo.

@Override
public DataView addTo(Schematic schematic, DataView data) {
    final int xMin = schematic.getBlockMin().getX();
    final int yMin = schematic.getBlockMin().getY();
    final int zMin = schematic.getBlockMin().getZ();
    final int width = schematic.getBlockSize().getX();
    final int height = schematic.getBlockSize().getY();
    final int length = schematic.getBlockSize().getZ();
    if (width > MAX_SIZE || height > MAX_SIZE || length > MAX_SIZE) {
        throw new IllegalArgumentException(String.format("Schematic is larger than maximum allowable size (found: (%d, %d, %d) max: (%d, %<d, %<d)", width, height, length, MAX_SIZE));
    }
    data.set(DataQueries.Schematic.WIDTH, width);
    data.set(DataQueries.Schematic.HEIGHT, height);
    data.set(DataQueries.Schematic.LENGTH, length);
    data.set(DataQueries.Schematic.VERSION, VERSION);
    for (DataQuery metaKey : schematic.getMetadata().getKeys(false)) {
        data.set(DataQueries.Schematic.METADATA.then(metaKey), schematic.getMetadata().get(metaKey).get());
    }
    int[] offset = new int[] { -xMin, -yMin, -zMin };
    data.set(DataQueries.Schematic.OFFSET, offset);
    BlockPalette palette = schematic.getPalette();
    ByteArrayOutputStream buffer = new ByteArrayOutputStream(width * height * length);
    for (int y = 0; y < height; y++) {
        int y0 = yMin + y;
        for (int z = 0; z < length; z++) {
            int z0 = zMin + z;
            for (int x = 0; x < width; x++) {
                int x0 = xMin + x;
                BlockState state = schematic.getBlock(x0, y0, z0);
                int id = palette.getOrAssign(state);
                while ((id & -128) != 0) {
                    buffer.write(id & 127 | 128);
                    id >>>= 7;
                }
                buffer.write(id);
            }
        }
    }
    data.set(DataQueries.Schematic.BLOCK_DATA, buffer.toByteArray());
    if (palette.getType() == BlockPaletteTypes.LOCAL) {
        DataQuery paletteQuery = DataQueries.Schematic.PALETTE;
        for (BlockState state : palette.getEntries()) {
            // getOrAssign to skip the optional, it will never assign
            data.set(paletteQuery.then(state.getId()), palette.getOrAssign(state));
        }
        data.set(DataQueries.Schematic.PALETTE_MAX, palette.getHighestId());
    }
    List<DataView> tileEntities = Lists.newArrayList();
    for (Map.Entry<Vector3i, TileEntityArchetype> entry : schematic.getTileEntityArchetypes().entrySet()) {
        Vector3i pos = entry.getKey();
        DataContainer tiledata = entry.getValue().getTileData();
        int[] apos = new int[] { pos.getX() - xMin, pos.getY() - yMin, pos.getZ() - zMin };
        tiledata.set(DataQueries.Schematic.TILEENTITY_POS, apos);
        if (!tiledata.contains(DataQueries.CONTENT_VERSION)) {
            // Set a default content version of 1
            tiledata.set(DataQueries.CONTENT_VERSION, 1);
        }
        tileEntities.add(tiledata);
    }
    data.set(DataQueries.Schematic.TILEENTITY_DATA, tileEntities);
    return data;
}
Also used : BlockPalette(org.spongepowered.api.world.schematic.BlockPalette) ByteArrayOutputStream(java.io.ByteArrayOutputStream) DataView(org.spongepowered.api.data.DataView) DataContainer(org.spongepowered.api.data.DataContainer) BlockState(org.spongepowered.api.block.BlockState) Vector3i(com.flowpowered.math.vector.Vector3i) DataQuery(org.spongepowered.api.data.DataQuery) TileEntityArchetype(org.spongepowered.api.block.tileentity.TileEntityArchetype) Map(java.util.Map)

Example 4 with BlockPalette

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

the class ArrayMutableBlockBuffer method setBlock.

@Override
public boolean setBlock(int x, int y, int z, BlockState block) {
    checkRange(x, y, z);
    int id = this.palette.getOrAssign(block);
    if (id > this.data.getMax()) {
        int highId = this.palette.getHighestId();
        int dataSize = area();
        BackingData newdata;
        if (highId * 2 > GlobalPalette.instance.getHighestId()) {
            // we are only saving about 1 bit at this point, so transition to a global palette
            BlockPalette newpalette = GlobalPalette.instance;
            id = newpalette.getOrAssign(block);
            highId = newpalette.getHighestId();
            newdata = new PackedBackingData(dataSize, highId);
            for (int i = 0; i < dataSize; i++) {
                newdata.set(i, newpalette.getOrAssign(this.palette.get(this.data.get(i)).orElse(AIR)));
            }
            this.palette = newpalette;
        } else {
            newdata = new PackedBackingData(dataSize, highId);
            for (int i = 0; i < dataSize; i++) {
                newdata.set(i, this.data.get(i));
            }
        }
        this.data = newdata;
    }
    this.data.set(getIndex(x, y, z), id);
    return true;
}
Also used : BlockPalette(org.spongepowered.api.world.schematic.BlockPalette)

Aggregations

BlockPalette (org.spongepowered.api.world.schematic.BlockPalette)4 Vector3i (com.flowpowered.math.vector.Vector3i)3 BlockState (org.spongepowered.api.block.BlockState)3 TileEntityArchetype (org.spongepowered.api.block.tileentity.TileEntityArchetype)3 DataView (org.spongepowered.api.data.DataView)3 ResourceLocation (net.minecraft.util.ResourceLocation)2 TileEntityType (org.spongepowered.api.block.tileentity.TileEntityType)2 DataQuery (org.spongepowered.api.data.DataQuery)2 InvalidDataException (org.spongepowered.api.data.persistence.InvalidDataException)2 SpongeTileEntityArchetypeBuilder (org.spongepowered.common.block.SpongeTileEntityArchetypeBuilder)2 ArrayMutableBlockBuffer (org.spongepowered.common.util.gen.ArrayMutableBlockBuffer)2 SpongeSchematic (org.spongepowered.common.world.schematic.SpongeSchematic)2 ByteArrayOutputStream (java.io.ByteArrayOutputStream)1 Map (java.util.Map)1 DataContainer (org.spongepowered.api.data.DataContainer)1 MutableBlockVolume (org.spongepowered.api.world.extent.MutableBlockVolume)1 Schematic (org.spongepowered.api.world.schematic.Schematic)1 BimapPalette (org.spongepowered.common.world.schematic.BimapPalette)1