Search in sources :

Example 46 with BaseBlock

use of com.sk89q.worldedit.world.block.BaseBlock in project FastAsyncWorldEdit by IntellectualSites.

the class MCEditSchematicReader method read.

@Override
public Clipboard read() throws IOException {
    // Schematic tag
    NamedTag rootTag = inputStream.readNamedTag();
    if (!rootTag.getName().equals("Schematic")) {
        throw new IOException("Tag 'Schematic' does not exist or is not first");
    }
    CompoundTag schematicTag = (CompoundTag) rootTag.getTag();
    // Check
    Map<String, Tag> schematic = schematicTag.getValue();
    if (!schematic.containsKey("Blocks")) {
        throw new IOException("Schematic file is missing a 'Blocks' tag");
    }
    // Check type of Schematic
    String materials = requireTag(schematic, "Materials", StringTag.class).getValue();
    if (!materials.equals("Alpha")) {
        throw new IOException("Schematic file is not an Alpha schematic");
    }
    // ====================================================================
    // Metadata
    // ====================================================================
    BlockVector3 origin;
    Region region;
    // Get information
    short width = requireTag(schematic, "Width", ShortTag.class).getValue();
    short height = requireTag(schematic, "Height", ShortTag.class).getValue();
    short length = requireTag(schematic, "Length", ShortTag.class).getValue();
    try {
        int originX = requireTag(schematic, "WEOriginX", IntTag.class).getValue();
        int originY = requireTag(schematic, "WEOriginY", IntTag.class).getValue();
        int originZ = requireTag(schematic, "WEOriginZ", IntTag.class).getValue();
        BlockVector3 min = BlockVector3.at(originX, originY, originZ);
        int offsetX = requireTag(schematic, "WEOffsetX", IntTag.class).getValue();
        int offsetY = requireTag(schematic, "WEOffsetY", IntTag.class).getValue();
        int offsetZ = requireTag(schematic, "WEOffsetZ", IntTag.class).getValue();
        BlockVector3 offset = BlockVector3.at(offsetX, offsetY, offsetZ);
        origin = min.subtract(offset);
        region = new CuboidRegion(min, min.add(width, height, length).subtract(BlockVector3.ONE));
    } catch (IOException ignored) {
        origin = BlockVector3.ZERO;
        region = new CuboidRegion(origin, origin.add(width, height, length).subtract(BlockVector3.ONE));
    }
    // ====================================================================
    // Blocks
    // ====================================================================
    // Get blocks
    byte[] blockId = requireTag(schematic, "Blocks", ByteArrayTag.class).getValue();
    byte[] blockData = requireTag(schematic, "Data", ByteArrayTag.class).getValue();
    byte[] addId = new byte[0];
    // Have to later combine IDs
    short[] blocks = new short[blockId.length];
    // the highest 4 bits are stored in a separate byte array.
    if (schematic.containsKey("AddBlocks")) {
        addId = requireTag(schematic, "AddBlocks", ByteArrayTag.class).getValue();
    }
    // Combine the AddBlocks data with the first 8-bit block ID
    for (int index = 0; index < blockId.length; index++) {
        if ((index >> 1) >= addId.length) {
            // No corresponding AddBlocks index
            blocks[index] = (short) (blockId[index] & 0xFF);
        } else {
            if ((index & 1) == 0) {
                blocks[index] = (short) (((addId[index >> 1] & 0x0F) << 8) + (blockId[index] & 0xFF));
            } else {
                blocks[index] = (short) (((addId[index >> 1] & 0xF0) << 4) + (blockId[index] & 0xFF));
            }
        }
    }
    // Need to pull out tile entities
    final ListTag tileEntityTag = getTag(schematic, "TileEntities", ListTag.class);
    List<Tag> tileEntities = tileEntityTag == null ? new ArrayList<>() : tileEntityTag.getValue();
    BlockMap<BaseBlock> tileEntityBlocks = BlockMap.createForBaseBlock();
    for (Tag tag : tileEntities) {
        if (!(tag instanceof CompoundTag)) {
            continue;
        }
        CompoundTag t = (CompoundTag) tag;
        Map<String, Tag> values = new HashMap<>(t.getValue());
        String id = t.getString("id");
        values.put("id", new StringTag(convertBlockEntityId(id)));
        int x = t.getInt("x");
        int y = t.getInt("y");
        int z = t.getInt("z");
        int index = y * width * length + z * width + x;
        // position in schematics?
        if (index >= blocks.length) {
            LOGGER.warn("Skipping corrupt tile entity at position {} {} {} in schematic.", x, y, z);
            continue;
        }
        BlockState block = getBlockState(blocks[index], blockData[index]);
        BlockState newBlock = block;
        if (newBlock != null) {
            for (NBTCompatibilityHandler handler : COMPATIBILITY_HANDLERS) {
                if (handler.isAffectedBlock(newBlock)) {
                    newBlock = handler.updateNBT(block, values).toImmutableState();
                    if (newBlock == null || values.isEmpty()) {
                        break;
                    }
                }
            }
        }
        if (values.isEmpty()) {
            t = null;
        } else {
            t = new CompoundTag(values);
        }
        if (fixer != null && t != null) {
            // FAWE start - BinaryTag
            t = (CompoundTag) AdventureNBTConverter.fromAdventure(fixer.fixUp(DataFixer.FixTypes.BLOCK_ENTITY, t.asBinaryTag(), -1));
        // FAWE end
        }
        BlockVector3 vec = BlockVector3.at(x, y, z);
        // Insert into the map if we have changed the block or have a tag
        BlockState blockToInsert = newBlock != null ? newBlock : (t != null ? block : null);
        if (blockToInsert != null) {
            BaseBlock baseBlock = t != null ? blockToInsert.toBaseBlock(new CompoundTag(t.getValue())) : blockToInsert.toBaseBlock();
            tileEntityBlocks.put(vec, baseBlock);
        }
    }
    BlockArrayClipboard clipboard = new BlockArrayClipboard(region);
    clipboard.setOrigin(origin);
    Set<Integer> unknownBlocks = new HashSet<>();
    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;
                BlockVector3 pt = BlockVector3.at(x, y, z);
                BaseBlock state = Optional.ofNullable(tileEntityBlocks.get(pt)).orElseGet(() -> {
                    BlockState blockState = getBlockState(blocks[index], blockData[index]);
                    return blockState == null ? null : blockState.toBaseBlock();
                });
                try {
                    if (state != null) {
                        clipboard.setBlock(region.getMinimumPoint().add(pt), state);
                    } else {
                        short block = blocks[index];
                        byte data = blockData[index];
                        int combined = block << 8 | data;
                        if (unknownBlocks.add(combined)) {
                            LOGGER.warn("Unknown block when loading schematic: {} {}. This is most likely a" + "bad schematic.", block, data);
                        }
                    }
                } catch (WorldEditException ignored) {
                // BlockArrayClipboard won't throw this
                }
            }
        }
    }
    // ====================================================================
    // Entities
    // ====================================================================
    ListTag entityList = getTag(schematic, "Entities", ListTag.class);
    if (entityList != null) {
        List<Tag> entityTags = entityList.getValue();
        for (Tag tag : entityTags) {
            if (tag instanceof CompoundTag) {
                CompoundTag compound = (CompoundTag) tag;
                if (fixer != null) {
                    // FAWE start - BinaryTag
                    compound = (CompoundTag) AdventureNBTConverter.fromAdventure(fixer.fixUp(DataFixer.FixTypes.ENTITY, compound.asBinaryTag(), -1));
                // FAWE end
                }
                String id = convertEntityId(compound.getString("id"));
                Location location = NBTConversions.toLocation(clipboard, compound.getListTag("Pos"), compound.getListTag("Rotation"));
                if (!id.isEmpty()) {
                    EntityType entityType = EntityTypes.get(id.toLowerCase(Locale.ROOT));
                    if (entityType != null) {
                        for (EntityNBTCompatibilityHandler compatibilityHandler : ENTITY_COMPATIBILITY_HANDLERS) {
                            if (compatibilityHandler.isAffectedEntity(entityType, compound)) {
                                compound = compatibilityHandler.updateNBT(entityType, compound);
                            }
                        }
                        BaseEntity state = new BaseEntity(entityType, compound);
                        clipboard.createEntity(location, state);
                    } else {
                        LOGGER.warn("Unknown entity when pasting schematic: " + id.toLowerCase(Locale.ROOT));
                    }
                }
            }
        }
    }
    return clipboard;
}
Also used : StringTag(com.sk89q.jnbt.StringTag) HashMap(java.util.HashMap) CuboidRegion(com.sk89q.worldedit.regions.CuboidRegion) BaseBlock(com.sk89q.worldedit.world.block.BaseBlock) EntityNBTCompatibilityHandler(com.sk89q.worldedit.extent.clipboard.io.legacycompat.EntityNBTCompatibilityHandler) NBTCompatibilityHandler(com.sk89q.worldedit.extent.clipboard.io.legacycompat.NBTCompatibilityHandler) EntityNBTCompatibilityHandler(com.sk89q.worldedit.extent.clipboard.io.legacycompat.EntityNBTCompatibilityHandler) NamedTag(com.sk89q.jnbt.NamedTag) CompoundTag(com.sk89q.jnbt.CompoundTag) IntTag(com.sk89q.jnbt.IntTag) HashSet(java.util.HashSet) BlockArrayClipboard(com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard) BaseEntity(com.sk89q.worldedit.entity.BaseEntity) IOException(java.io.IOException) BlockVector3(com.sk89q.worldedit.math.BlockVector3) ListTag(com.sk89q.jnbt.ListTag) ShortTag(com.sk89q.jnbt.ShortTag) EntityType(com.sk89q.worldedit.world.entity.EntityType) BlockState(com.sk89q.worldedit.world.block.BlockState) CuboidRegion(com.sk89q.worldedit.regions.CuboidRegion) Region(com.sk89q.worldedit.regions.Region) StringTag(com.sk89q.jnbt.StringTag) ShortTag(com.sk89q.jnbt.ShortTag) ListTag(com.sk89q.jnbt.ListTag) IntTag(com.sk89q.jnbt.IntTag) NamedTag(com.sk89q.jnbt.NamedTag) ByteArrayTag(com.sk89q.jnbt.ByteArrayTag) CompoundTag(com.sk89q.jnbt.CompoundTag) Tag(com.sk89q.jnbt.Tag) WorldEditException(com.sk89q.worldedit.WorldEditException) ByteArrayTag(com.sk89q.jnbt.ByteArrayTag) Location(com.sk89q.worldedit.util.Location)

Example 47 with BaseBlock

use of com.sk89q.worldedit.world.block.BaseBlock in project FastAsyncWorldEdit by IntellectualSites.

the class SpongeSchematicWriter method write2.

/**
 * Writes a version 2 schematic file.
 *
 * @param clipboard The clipboard
 * @return The schematic map
 */
private Map<String, Tag> write2(Clipboard clipboard) {
    Region region = clipboard.getRegion();
    BlockVector3 origin = clipboard.getOrigin();
    BlockVector3 min = region.getMinimumPoint();
    BlockVector3 offset = min.subtract(origin);
    int width = region.getWidth();
    int height = region.getHeight();
    int length = region.getLength();
    if (width > MAX_SIZE) {
        throw new IllegalArgumentException("Width of region too large for a .schematic");
    }
    if (height > MAX_SIZE) {
        throw new IllegalArgumentException("Height of region too large for a .schematic");
    }
    if (length > MAX_SIZE) {
        throw new IllegalArgumentException("Length of region too large for a .schematic");
    }
    Map<String, Tag> schematic = new HashMap<>();
    schematic.put("Version", new IntTag(CURRENT_VERSION));
    schematic.put("DataVersion", new IntTag(WorldEdit.getInstance().getPlatformManager().queryCapability(Capability.WORLD_EDITING).getDataVersion()));
    Map<String, Tag> metadata = new HashMap<>();
    metadata.put("WEOffsetX", new IntTag(offset.getBlockX()));
    metadata.put("WEOffsetY", new IntTag(offset.getBlockY()));
    metadata.put("WEOffsetZ", new IntTag(offset.getBlockZ()));
    metadata.put("FAWEVersion", new IntTag(Fawe.instance().getVersion().build));
    schematic.put("Metadata", new CompoundTag(metadata));
    schematic.put("Width", new ShortTag((short) width));
    schematic.put("Height", new ShortTag((short) height));
    schematic.put("Length", new ShortTag((short) length));
    // The Sponge format Offset refers to the 'min' points location in the world. That's our 'Origin'
    schematic.put("Offset", new IntArrayTag(new int[] { min.getBlockX(), min.getBlockY(), min.getBlockZ() }));
    int paletteMax = 0;
    Map<String, Integer> palette = new HashMap<>();
    List<CompoundTag> tileEntities = new ArrayList<>();
    ByteArrayOutputStream buffer = new ByteArrayOutputStream(width * height * length);
    for (int y = 0; y < height; y++) {
        int y0 = min.getBlockY() + y;
        for (int z = 0; z < length; z++) {
            int z0 = min.getBlockZ() + z;
            for (int x = 0; x < width; x++) {
                int x0 = min.getBlockX() + x;
                BlockVector3 point = BlockVector3.at(x0, y0, z0);
                BaseBlock block = clipboard.getFullBlock(point);
                if (block.getNbtData() != null) {
                    Map<String, Tag> values = new HashMap<>(block.getNbtData().getValue());
                    // Remove 'id' if it exists. We want 'Id'
                    values.remove("id");
                    // Positions are kept in NBT, we don't want that.
                    values.remove("x");
                    values.remove("y");
                    values.remove("z");
                    values.put("Id", new StringTag(block.getNbtId()));
                    values.put("Pos", new IntArrayTag(new int[] { x, y, z }));
                    tileEntities.add(new CompoundTag(values));
                }
                String blockKey = block.toImmutableState().getAsString();
                int blockId;
                if (palette.containsKey(blockKey)) {
                    blockId = palette.get(blockKey);
                } else {
                    blockId = paletteMax;
                    palette.put(blockKey, blockId);
                    paletteMax++;
                }
                while ((blockId & -128) != 0) {
                    buffer.write(blockId & 127 | 128);
                    blockId >>>= 7;
                }
                buffer.write(blockId);
            }
        }
    }
    schematic.put("PaletteMax", new IntTag(paletteMax));
    Map<String, Tag> paletteTag = new HashMap<>();
    palette.forEach((key, value) -> paletteTag.put(key, new IntTag(value)));
    schematic.put("Palette", new CompoundTag(paletteTag));
    schematic.put("BlockData", new ByteArrayTag(buffer.toByteArray()));
    schematic.put("BlockEntities", new ListTag(CompoundTag.class, tileEntities));
    // version 2 stuff
    if (clipboard.hasBiomes()) {
        writeBiomes(clipboard, schematic);
    }
    if (!clipboard.getEntities().isEmpty()) {
        writeEntities(clipboard, schematic);
    }
    return schematic;
}
Also used : StringTag(com.sk89q.jnbt.StringTag) IntArrayTag(com.sk89q.jnbt.IntArrayTag) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) ByteArrayOutputStream(java.io.ByteArrayOutputStream) BlockVector3(com.sk89q.worldedit.math.BlockVector3) BaseBlock(com.sk89q.worldedit.world.block.BaseBlock) ListTag(com.sk89q.jnbt.ListTag) ShortTag(com.sk89q.jnbt.ShortTag) Region(com.sk89q.worldedit.regions.Region) StringTag(com.sk89q.jnbt.StringTag) ShortTag(com.sk89q.jnbt.ShortTag) IntArrayTag(com.sk89q.jnbt.IntArrayTag) ListTag(com.sk89q.jnbt.ListTag) IntTag(com.sk89q.jnbt.IntTag) ByteArrayTag(com.sk89q.jnbt.ByteArrayTag) CompoundTag(com.sk89q.jnbt.CompoundTag) Tag(com.sk89q.jnbt.Tag) IntTag(com.sk89q.jnbt.IntTag) CompoundTag(com.sk89q.jnbt.CompoundTag) ByteArrayTag(com.sk89q.jnbt.ByteArrayTag)

Example 48 with BaseBlock

use of com.sk89q.worldedit.world.block.BaseBlock in project FastAsyncWorldEdit by IntellectualSites.

the class ExtentBlockCopy method apply.

@Override
public boolean apply(BlockVector3 position) throws WorldEditException {
    BaseBlock block = source.getFullBlock(position);
    BlockVector3 orig = position.subtract(from);
    BlockVector3 transformed = transform.apply(orig.toVector3()).toBlockPoint();
    // Apply transformations to NBT data if necessary
    block = transformNbtData(block);
    return destination.setBlock(transformed.add(to), block);
}
Also used : BlockVector3(com.sk89q.worldedit.math.BlockVector3) BaseBlock(com.sk89q.worldedit.world.block.BaseBlock)

Example 49 with BaseBlock

use of com.sk89q.worldedit.world.block.BaseBlock in project FastAsyncWorldEdit by IntellectualSites.

the class MultiStageReorder method setBlock.

@Override
public <B extends BlockStateHolder<B>> boolean setBlock(BlockVector3 location, B block) throws WorldEditException {
    if (!enabled) {
        return setDelegateBlock(location, block);
    }
    BlockState existing = getExtent().getBlock(location);
    PlacementPriority priority = getPlacementPriority(block);
    PlacementPriority srcPriority = getPlacementPriority(existing);
    if (srcPriority != PlacementPriority.FIRST) {
        BaseBlock replacement = (block.getBlockType().getMaterial().isAir() ? block : BlockTypes.AIR.getDefaultState()).toBaseBlock();
        switch(srcPriority) {
            case FINAL:
                stages.get(PlacementPriority.CLEAR_FINAL).put(location, replacement);
                break;
            case LATE:
                stages.get(PlacementPriority.CLEAR_LATE).put(location, replacement);
                break;
            case LAST:
                stages.get(PlacementPriority.CLEAR_LAST).put(location, replacement);
                break;
            default:
                break;
        }
        if (block.getBlockType().getMaterial().isAir()) {
            return !existing.equalsFuzzy(block);
        }
    }
    stages.get(priority).put(location, block.toBaseBlock());
    return !existing.equalsFuzzy(block);
}
Also used : BlockState(com.sk89q.worldedit.world.block.BlockState) BaseBlock(com.sk89q.worldedit.world.block.BaseBlock)

Example 50 with BaseBlock

use of com.sk89q.worldedit.world.block.BaseBlock in project WorldGuard by EngineHub.

the class SpongeUtil method clearSpongeWater.

/**
 * Remove water around a sponge.
 *
 * @param world The world the sponge is in
 * @param ox The x coordinate of the 'sponge' block
 * @param oy The y coordinate of the 'sponge' block
 * @param oz The z coordinate of the 'sponge' block
 */
public static void clearSpongeWater(World world, int ox, int oy, int oz) {
    WorldConfiguration wcfg = WorldGuard.getInstance().getPlatform().getGlobalStateManager().get(world);
    for (int cx = -wcfg.spongeRadius; cx <= wcfg.spongeRadius; cx++) {
        for (int cy = -wcfg.spongeRadius; cy <= wcfg.spongeRadius; cy++) {
            for (int cz = -wcfg.spongeRadius; cz <= wcfg.spongeRadius; cz++) {
                BlockVector3 vector = BlockVector3.at(ox + cx, oy + cy, oz + cz);
                BaseBlock block = world.getFullBlock(vector);
                BlockType blockType = block.getBlockType();
                if (isReplacable(blockType)) {
                    try {
                        world.setBlock(vector, BlockTypes.AIR.getDefaultState());
                    } catch (WorldEditException e) {
                        e.printStackTrace();
                    }
                } else {
                    @SuppressWarnings("unchecked") Property<Object> waterloggedProp = waterloggable.computeIfAbsent(blockType, (bt -> (Property<Object>) bt.getPropertyMap().get("waterlogged")));
                    if (waterloggedProp != null) {
                        try {
                            world.setBlock(vector, block.with(waterloggedProp, false));
                        } catch (WorldEditException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }
    }
}
Also used : Property(com.sk89q.worldedit.registry.state.Property) WorldEditException(com.sk89q.worldedit.WorldEditException) BlockTypes(com.sk89q.worldedit.world.block.BlockTypes) BlockVector3(com.sk89q.worldedit.math.BlockVector3) BlockType(com.sk89q.worldedit.world.block.BlockType) WorldConfiguration(com.sk89q.worldguard.config.WorldConfiguration) WorldGuard(com.sk89q.worldguard.WorldGuard) Map(java.util.Map) World(com.sk89q.worldedit.world.World) BaseBlock(com.sk89q.worldedit.world.block.BaseBlock) Maps(com.google.common.collect.Maps) WorldConfiguration(com.sk89q.worldguard.config.WorldConfiguration) BlockType(com.sk89q.worldedit.world.block.BlockType) BlockVector3(com.sk89q.worldedit.math.BlockVector3) WorldEditException(com.sk89q.worldedit.WorldEditException) BaseBlock(com.sk89q.worldedit.world.block.BaseBlock) Property(com.sk89q.worldedit.registry.state.Property)

Aggregations

BaseBlock (com.sk89q.worldedit.world.block.BaseBlock)50 BlockVector3 (com.sk89q.worldedit.math.BlockVector3)22 BlockState (com.sk89q.worldedit.world.block.BlockState)10 CompoundTag (com.sk89q.jnbt.CompoundTag)9 HashMap (java.util.HashMap)7 Tag (com.sk89q.jnbt.Tag)6 Location (com.sk89q.worldedit.util.Location)6 World (com.sk89q.worldedit.world.World)6 BlockType (com.sk89q.worldedit.world.block.BlockType)6 IOException (java.io.IOException)6 MutableBlockVector3 (com.fastasyncworldedit.core.math.MutableBlockVector3)5 ListTag (com.sk89q.jnbt.ListTag)5 StringTag (com.sk89q.jnbt.StringTag)5 WorldEditException (com.sk89q.worldedit.WorldEditException)5 ArrayList (java.util.ArrayList)5 IntTag (com.sk89q.jnbt.IntTag)4 BaseEntity (com.sk89q.worldedit.entity.BaseEntity)4 CuboidRegion (com.sk89q.worldedit.regions.CuboidRegion)4 Region (com.sk89q.worldedit.regions.Region)4 NamedTag (com.sk89q.jnbt.NamedTag)3