From 814a5f43641c78fda87933694656afbe6f3bfc34 Mon Sep 17 00:00:00 2001 From: yoyosource Date: Sat, 29 Jul 2023 12:47:48 +0200 Subject: [PATCH] Add PasteBuilder as the new alternative to pasting via region.reset Signed-off-by: yoyosource --- .../bausystem/utils/FlatteningWrapper15.java | 136 ++++++++++++++++-- .../features/region/TestblockCommand.java | 1 - .../bausystem/region/PasteOptions.java | 2 + .../bausystem/utils/FlatteningWrapper.java | 6 +- .../bausystem/utils/PasteBuilder.java | 116 +++++++++++++++ 5 files changed, 245 insertions(+), 16 deletions(-) create mode 100644 BauSystem_Main/src/de/steamwar/bausystem/utils/PasteBuilder.java diff --git a/BauSystem_15/src/de/steamwar/bausystem/utils/FlatteningWrapper15.java b/BauSystem_15/src/de/steamwar/bausystem/utils/FlatteningWrapper15.java index 4b69606e..e45f3cdc 100644 --- a/BauSystem_15/src/de/steamwar/bausystem/utils/FlatteningWrapper15.java +++ b/BauSystem_15/src/de/steamwar/bausystem/utils/FlatteningWrapper15.java @@ -65,6 +65,7 @@ import java.util.Arrays; import java.util.HashSet; import java.util.Objects; import java.util.Set; +import java.util.function.BiPredicate; import java.util.logging.Level; public class FlatteningWrapper15 implements FlatteningWrapper { @@ -113,6 +114,75 @@ public class FlatteningWrapper15 implements FlatteningWrapper { WORLDEDIT_PLUGIN.getSession(p).setRegionSelector(BUKKITWORLD, new CuboidRegionSelector(BUKKITWORLD, toBlockVector3(minPoint), toBlockVector3(maxPoint))); } + @Override + public Clipboard loadSchematic(File file) { + Clipboard clipboard; + try (ClipboardReader reader = Objects.requireNonNull(ClipboardFormats.findByFile(file)).getReader(new FileInputStream(file))) { + clipboard = reader.read(); + } catch (NullPointerException | IOException e) { + throw new SecurityException("Bausystem schematic not found", e); + } + return clipboard; + } + + @Override + public EditSession paste(PasteBuilder pasteBuilder) { + try (EditSession e = WorldEdit.getInstance().getEditSessionFactory().getEditSession(new BukkitWorld(Bukkit.getWorlds().get(0)), -1)) { + Clipboard clipboard = pasteBuilder.getClipboard(); + + BlockVector3 minimum = clipboard.getRegion().getMinimumPoint(); + for (int x = 0; x < clipboard.getDimensions().getX(); x++) { + for (int y = 0; y < clipboard.getDimensions().getY(); y++) { + for (int z = 0; z < clipboard.getDimensions().getZ(); z++) { + BlockVector3 pos = minimum.add(x, y, z); + pasteBuilder.getMappers().forEach(mapper -> mapper.accept(clipboard, pos)); + } + } + } + + e.setMask(new Mask() { + @Override + public boolean test(BlockVector3 blockVector3) { + if (pasteBuilder.getPredicates().isEmpty()) return true; + BaseBlock block = clipboard.getFullBlock(blockVector3); + String blockName = block.toString().toLowerCase(); + for (BiPredicate predicate : pasteBuilder.getPredicates()) { + if (!predicate.test(block, blockName)) return false; + } + return true; + } + + @Nullable + @Override + public Mask2D toMask2D() { + return null; + } + }); + + ClipboardHolder ch = new ClipboardHolder(clipboard); + BlockVector3 dimensions = clipboard.getDimensions(); + BlockVector3 v = BlockVector3.at(pasteBuilder.getPastPoint().getX(), pasteBuilder.getPastPoint().getY(), pasteBuilder.getPastPoint().getZ()); + BlockVector3 offset = clipboard.getRegion().getMinimumPoint().subtract(clipboard.getOrigin()); + if (pasteBuilder.isRotate()) { + ch.setTransform(new AffineTransform().rotateY(180)); + v = v.add(dimensions.getX() / 2, 0, dimensions.getZ() / 2).subtract(offset.multiply(-1, 1, -1)).subtract(0, 0, 1); + } else { + v = v.subtract(dimensions.getX() / 2, 0, dimensions.getZ() / 2).subtract(offset); + } + + if (pasteBuilder.isReset()) { + e.setBlocks(new CuboidRegion(toBlockVector3(pasteBuilder.getMinPoint()), toBlockVector3(pasteBuilder.getMaxPoint())), Objects.requireNonNull(BlockTypes.AIR).getDefaultState().toBaseBlock()); + if (pasteBuilder.getWaterLevel() != 0) { + e.setBlocks(new CuboidRegion(toBlockVector3(pasteBuilder.getMinPoint()), toBlockVector3(pasteBuilder.getMaxPoint()).withY(pasteBuilder.getWaterLevel())), Objects.requireNonNull(BlockTypes.WATER).getDefaultState().toBaseBlock()); + } + } + Operations.completeBlindly(ch.createPaste(e).to(v).ignoreAirBlocks(pasteBuilder.isIgnoreAir()).build()); + return e; + } catch (WorldEditException e) { + throw new SecurityException(e.getMessage(), e); + } + } + private static final BaseBlock WOOL = Objects.requireNonNull(BlockTypes.PINK_WOOL).getDefaultState().toBaseBlock(); private static final BaseBlock CLAY = Objects.requireNonNull(BlockTypes.PINK_TERRACOTTA).getDefaultState().toBaseBlock(); private static final BaseBlock GLAZED = Objects.requireNonNull(BlockTypes.PINK_GLAZED_TERRACOTTA).getDefaultState().toBaseBlock(); @@ -141,6 +211,12 @@ public class FlatteningWrapper15 implements FlatteningWrapper { if (pasteOptions.getColor() != Color.PINK) { changeColor(clipboard, pasteOptions.getColor()); } + if (pasteOptions.isTestBlock() && pasteOptions.isRemoveTNT()) { + removeTNT(clipboard); + } + if (pasteOptions.isTestBlock() && pasteOptions.isRemoveWater()) { + removeWater(clipboard); + } Set blocks = new HashSet<>(); { @@ -160,18 +236,7 @@ public class FlatteningWrapper15 implements FlatteningWrapper { BaseBlock block = clipboard.getFullBlock(blockVector3); String blockName = block.toString().toLowerCase(); - if (blocks.contains(blockName) && pasteOptions.isOnlyColors()) return true; - if (pasteOptions.isTestBlock()) { - if (blockName.startsWith("minecraft:water")) return false; - if (blockName.contains("waterlogged=true")) try { - e.setBlock(blockVector3, new WaterloggedRemover(clipboard).applyBlock(blockVector3)); - } catch (WorldEditException ex) { - throw new RuntimeException(ex); - } - if (blockName.startsWith("minecraft:tnt") && pasteOptions.isRemoveTNT()) return false; - } - - + if (pasteOptions.isOnlyColors()) return blocks.contains(blockName); return true; } @@ -209,7 +274,6 @@ public class FlatteningWrapper15 implements FlatteningWrapper { } } - @Override public void changeColor(Clipboard clipboard, Color color) throws WorldEditException { BlockVector3 minimum = clipboard.getRegion().getMinimumPoint(); BaseBlock wool = Objects.requireNonNull(BlockTypes.get(color.name().toLowerCase() + "_wool")).getDefaultState().toBaseBlock(); @@ -248,6 +312,52 @@ public class FlatteningWrapper15 implements FlatteningWrapper { } } + public void removeTNT(Clipboard clipboard) throws WorldEditException { + BlockVector3 minimum = clipboard.getRegion().getMinimumPoint(); + BaseBlock tnt = Objects.requireNonNull(BlockTypes.get("tnt")).getDefaultState().toBaseBlock(); + BaseBlock air = Objects.requireNonNull(BlockTypes.get("air")).getDefaultState().toBaseBlock(); + + for (int x = 0; x < clipboard.getDimensions().getX(); x++) { + for (int y = 0; y < clipboard.getDimensions().getY(); y++) { + for (int z = 0; z < clipboard.getDimensions().getZ(); z++) { + BlockVector3 pos = minimum.add(x, y, z); + BaseBlock block = clipboard.getFullBlock(pos); + + if (block.equals(tnt)) { + clipboard.setBlock(pos, air); + } + } + } + } + } + + public void removeWater(Clipboard clipboard) throws WorldEditException { + BlockVector3 minimum = clipboard.getRegion().getMinimumPoint(); + BaseBlock water = Objects.requireNonNull(BlockTypes.get("water")).getDefaultState().toBaseBlock(); + BaseBlock air = Objects.requireNonNull(BlockTypes.get("air")).getDefaultState().toBaseBlock(); + WaterloggedRemover waterloggedRemover = new WaterloggedRemover(clipboard); + + for (int x = 0; x < clipboard.getDimensions().getX(); x++) { + for (int y = 0; y < clipboard.getDimensions().getY(); y++) { + for (int z = 0; z < clipboard.getDimensions().getZ(); z++) { + BlockVector3 pos = minimum.add(x, y, z); + BaseBlock block = clipboard.getFullBlock(pos); + + if (block.equals(water)) { + clipboard.setBlock(pos, air); + } else { + String blockName = block.getBlockType().getName(); + if (blockName.equals("Water")) { + clipboard.setBlock(pos, air); + } else if (blockName.contains("waterlogged=true")) { + clipboard.setBlock(pos, waterloggedRemover.applyBlock(pos)); + } + } + } + } + } + } + @Override public boolean backup(Point minPoint, Point maxPoint, File file) { BukkitWorld bukkitWorld = new BukkitWorld(Bukkit.getWorlds().get(0)); diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/region/TestblockCommand.java b/BauSystem_Main/src/de/steamwar/bausystem/features/region/TestblockCommand.java index 64164912..5fc76808 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/region/TestblockCommand.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/region/TestblockCommand.java @@ -66,7 +66,6 @@ public class TestblockCommand extends SWCommand { @Register public void schematicTestblockCommand(@Validator Player p, @Mapper("withPublic") SchematicNode node, TestblockParameterType... testblockParameterTypes) { Set testblockParameterTypesSet = new HashSet<>(Arrays.asList(testblockParameterTypes)); - System.out.println(testblockParameterTypesSet); boolean isExtension = testblockParameterTypesSet.contains(TestblockParameterType.EXTENSION); boolean isIgnoreAir = testblockParameterTypesSet.contains(TestblockParameterType.IGNORE_AIR); boolean isOnlyColor = testblockParameterTypesSet.contains(TestblockParameterType.ONLY_COLOR); diff --git a/BauSystem_Main/src/de/steamwar/bausystem/region/PasteOptions.java b/BauSystem_Main/src/de/steamwar/bausystem/region/PasteOptions.java index ec8186f4..5be73fe6 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/region/PasteOptions.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/region/PasteOptions.java @@ -22,10 +22,12 @@ package de.steamwar.bausystem.region; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; +import lombok.ToString; @Getter @Builder @AllArgsConstructor +@ToString public class PasteOptions { private final boolean rotate; diff --git a/BauSystem_Main/src/de/steamwar/bausystem/utils/FlatteningWrapper.java b/BauSystem_Main/src/de/steamwar/bausystem/utils/FlatteningWrapper.java index 430bfe90..e80c4027 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/utils/FlatteningWrapper.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/utils/FlatteningWrapper.java @@ -46,9 +46,11 @@ public interface FlatteningWrapper { boolean isWorldEditCommand(String command); void setSelection(Player p, Point minPoint, Point maxPoint); + Clipboard loadSchematic(File file); + EditSession paste(PasteBuilder pasteBuilder); + EditSession paste(File file, Point pastePoint, PasteOptions pasteOptions); - EditSession paste(Clipboard clipboard, Point pastePoint, PasteOptions pasteOptions); - void changeColor(Clipboard clipboard, Color color) throws WorldEditException; + EditSession paste(Clipboard clipboard, Point pastePoint, PasteOptions pasteOptions); boolean backup(Point minPoint, Point maxPoint, File file); boolean inWater(World world, Vector tntPosition); diff --git a/BauSystem_Main/src/de/steamwar/bausystem/utils/PasteBuilder.java b/BauSystem_Main/src/de/steamwar/bausystem/utils/PasteBuilder.java new file mode 100644 index 00000000..b06cb221 --- /dev/null +++ b/BauSystem_Main/src/de/steamwar/bausystem/utils/PasteBuilder.java @@ -0,0 +1,116 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2023 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.bausystem.utils; + +import com.sk89q.worldedit.EditSession; +import com.sk89q.worldedit.extent.clipboard.Clipboard; +import com.sk89q.worldedit.math.BlockVector3; +import com.sk89q.worldedit.world.block.BaseBlock; +import de.steamwar.bausystem.region.Point; +import de.steamwar.sql.SchematicData; +import de.steamwar.sql.SchematicNode; +import lombok.Getter; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.function.BiConsumer; +import java.util.function.BiPredicate; + +@Getter +public class PasteBuilder { + + private final Clipboard clipboard; + private Point pastPoint; + private boolean rotate; + private boolean ignoreAir; + private boolean reset; + private Point minPoint; + private Point maxPoint; + private int waterLevel; + private List> predicates = new ArrayList<>(); + private List> mappers = new ArrayList<>(); + + public PasteBuilder(SchematicNode schematic) { + try { + this.clipboard = new SchematicData(schematic).load(); + } catch (IOException e) { + throw new SecurityException(e); + } + } + + public PasteBuilder(Clipboard clipboard) { + this.clipboard = clipboard; + } + + public PasteBuilder(File file) { + this.clipboard = FlatteningWrapper.impl.loadSchematic(file); + } + + public PasteBuilder pastePoint(Point point) { + this.pastPoint = point; + return this; + } + + public PasteBuilder rotate() { + this.rotate = true; + return this; + } + + public PasteBuilder ignoreAir() { + this.ignoreAir = true; + return this; + } + + public PasteBuilder reset() { + this.reset = true; + return this; + } + + public PasteBuilder minPoint(Point point) { + this.minPoint = point; + return this; + } + + public PasteBuilder maxPoint(Point point) { + this.maxPoint = point; + return this; + } + + public PasteBuilder waterLevel(int waterLevel) { + this.waterLevel = waterLevel; + return this; + } + + public PasteBuilder only(BiPredicate predicate) { + predicates.add(predicate); + return this; + } + + public PasteBuilder map(BiConsumer mapper) { + mappers.add(mapper); + return this; + } + + public EditSession run() { + return FlatteningWrapper.impl.paste(this); + } +}