diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/io/schematic/MinecraftStructure.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/io/schematic/MinecraftStructure.java index 18e7d4b99b..bd204c71e4 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/io/schematic/MinecraftStructure.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/io/schematic/MinecraftStructure.java @@ -103,6 +103,9 @@ public Clipboard read(UUID clipboardId) throws IOException { size.get(0).valueAsInt(), size.get(1).valueAsInt(), size.get(2).value() ).subtract(BlockVector3.ONE)); final Clipboard clipboard = new BlockArrayClipboard(region, clipboardId); + // fill clipboard with structure void blocks to represent empty entries. + // known block data will be overridden with palette data. + clipboard.setBlocks((Region) region, BlockTypes.STRUCTURE_VOID.getDefaultState()); // Palette final List paletteEntry = parent.getListTag("palette", LinTagType.compoundTag()).value(); @@ -204,6 +207,7 @@ public void write(Clipboard clipboard) throws IOException { Int2ObjectMap paletteIndexes = new Int2ObjectArrayMap<>(); for (final BlockVector3 pos : clipboard) { final BlockState block = clipboard.getBlock(pos); + // Structure Void Blocks are not part of the structure file and therefor not part of the palette if (block.getBlockType() == BlockTypes.STRUCTURE_VOID || ordinals.containsKey(block.getOrdinalChar())) { continue; } @@ -225,7 +229,11 @@ public void write(Clipboard clipboard) throws IOException { // Blocks LinListTag.Builder<@org.jetbrains.annotations.NotNull LinCompoundTag> blocks = LinListTag.builder(LinTagType.compoundTag()); for (final BlockVector3 pos : clipboard) { - final BlockState block = clipboard.getBlock(pos); + final BaseBlock block = clipboard.getFullBlock(pos); + // Structure Void Blocks are not part of the structure file + if (block.getBlockType() == BlockTypes.STRUCTURE_VOID) { + continue; + } LinCompoundTag.Builder entry = LinCompoundTag.builder() .putInt("state", ordinals.get(block.getOrdinalChar())) .put("pos", LinListTag.of(LinTagType.intTag(), List.of( @@ -233,12 +241,9 @@ public void write(Clipboard clipboard) throws IOException { LinIntTag.of(pos.y() - min.y()), LinIntTag.of(pos.z() - min.z()) ))); - final BaseBlock baseBlock = clipboard.getFullBlock(pos); - if (baseBlock != null) { - final LinCompoundTag nbt = baseBlock.getNbt(); - if (nbt != null) { - entry.put("nbt", nbt.toBuilder().remove("x").remove("y").remove("z").build()); - } + final LinCompoundTag nbt = block.getNbt(); + if (nbt != null) { + entry.put("nbt", nbt.toBuilder().remove("x").remove("y").remove("z").build()); } blocks.add(entry.build()); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/ClipboardCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/ClipboardCommands.java index 36cb2151e4..1f90c4337c 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/ClipboardCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/ClipboardCommands.java @@ -58,6 +58,7 @@ import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormats; import com.sk89q.worldedit.extent.clipboard.io.ClipboardWriter; import com.sk89q.worldedit.function.block.BlockReplace; +import com.sk89q.worldedit.function.mask.InverseSingleBlockTypeMask; import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.function.mask.MaskIntersection; import com.sk89q.worldedit.function.mask.Masks; @@ -85,6 +86,7 @@ import com.sk89q.worldedit.util.formatting.text.TextComponent; import com.sk89q.worldedit.util.formatting.text.event.ClickEvent; import com.sk89q.worldedit.world.World; +import com.sk89q.worldedit.world.block.BlockTypes; import org.enginehub.piston.annotation.Command; import org.enginehub.piston.annotation.CommandContainer; import org.enginehub.piston.annotation.param.Arg; @@ -526,14 +528,15 @@ public void paste( Mask sourceMask, //FAWE start - entity removal @Switch(name = 'x', desc = "Remove existing entities in the affected region") - boolean removeEntities + boolean removeEntities, + @Switch(name = 'v', desc = "Don't paste structure void blocks and keep the target block state") + boolean ignoreStructureVoidBlocks //FAWE end - ) throws WorldEditException { ClipboardHolder holder = session.getClipboard(); //FAWE start - use place - if (holder.getTransform().isIdentity() && sourceMask == null) { + if (holder.getTransform().isIdentity() && sourceMask == null && !ignoreStructureVoidBlocks) { place(actor, world, session, editSession, ignoreAirBlocks, atOrigin, selectPasted, onlySelect, pasteEntities, pasteBiomes, removeEntities ); @@ -550,13 +553,16 @@ public void paste( //FAWE end if (!onlySelect) { + final Mask finalSourceMask = ignoreStructureVoidBlocks ? + MaskIntersection.of(sourceMask, new InverseSingleBlockTypeMask(clipboard, BlockTypes.STRUCTURE_VOID)) : + sourceMask; Operation operation = holder .createPaste(editSession) .to(to) .ignoreAirBlocks(ignoreAirBlocks) .copyBiomes(pasteBiomes) .copyEntities(pasteEntities) - .maskSource(sourceMask) + .maskSource(finalSourceMask) .build(); Operations.completeLegacy(operation); messages.addAll(Lists.newArrayList(operation.getStatusMessages()));