diff --git a/BauSystem_15/src/de/steamwar/bausystem/utils/FlatteningWrapper15.java b/BauSystem_15/src/de/steamwar/bausystem/utils/FlatteningWrapper15.java index bcb52882..0a01fb42 100644 --- a/BauSystem_15/src/de/steamwar/bausystem/utils/FlatteningWrapper15.java +++ b/BauSystem_15/src/de/steamwar/bausystem/utils/FlatteningWrapper15.java @@ -37,14 +37,11 @@ import com.sk89q.worldedit.function.operation.Operations; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.transform.AffineTransform; import com.sk89q.worldedit.regions.CuboidRegion; -import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.regions.selector.CuboidRegionSelector; import com.sk89q.worldedit.session.ClipboardHolder; import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BlockTypes; -import de.steamwar.bausystem.region.Color; -import de.steamwar.bausystem.region.PasteOptions; import de.steamwar.bausystem.region.Point; import org.bukkit.Bukkit; import org.bukkit.Material; @@ -60,7 +57,12 @@ import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; -import java.util.*; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Objects; +import java.util.Set; +import java.util.concurrent.atomic.AtomicReference; +import java.util.function.BiPredicate; import java.util.logging.Level; public class FlatteningWrapper15 implements FlatteningWrapper { @@ -109,51 +111,49 @@ public class FlatteningWrapper15 implements FlatteningWrapper { WORLDEDIT_PLUGIN.getSession(p).setRegionSelector(BUKKITWORLD, new CuboidRegionSelector(BUKKITWORLD, toBlockVector3(minPoint), toBlockVector3(maxPoint))); } - 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(); - private static final BaseBlock GLASS = Objects.requireNonNull(BlockTypes.PINK_STAINED_GLASS).getDefaultState().toBaseBlock(); - private static final BaseBlock GLASS_PANE = Objects.requireNonNull(BlockTypes.PINK_STAINED_GLASS_PANE).getDefaultState().toBaseBlock(); - private static final BaseBlock CONCRETE = Objects.requireNonNull(BlockTypes.PINK_CONCRETE).getDefaultState().toBaseBlock(); - private static final BaseBlock CONCRETE_POWDER = Objects.requireNonNull(BlockTypes.PINK_CONCRETE_POWDER).getDefaultState().toBaseBlock(); - private static final BaseBlock CARPET = Objects.requireNonNull(BlockTypes.PINK_CARPET).getDefaultState().toBaseBlock(); - @Override - public EditSession paste(File file, Point pastePoint, PasteOptions pasteOptions) { + 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); } - - EditSession editSession = paste(clipboard, pastePoint, pasteOptions); - return editSession; + return clipboard; } @Override - public EditSession paste(Clipboard clipboard, Point pastePoint, PasteOptions pasteOptions) { + public EditSession paste(PasteBuilder pasteBuilder) { try (EditSession e = WorldEdit.getInstance().getEditSessionFactory().getEditSession(new BukkitWorld(Bukkit.getWorlds().get(0)), -1)) { - if (pasteOptions.getColor() != Color.PINK) { - changeColor(clipboard, pasteOptions.getColor()); - } - if (pasteOptions.isOnlyColors()) { - Set blocks = new HashSet<>(); - blocks.add("minecraft:" + pasteOptions.getColor().name().toLowerCase() + "_wool"); - blocks.add("minecraft:" + pasteOptions.getColor().name().toLowerCase() + "_terracotta"); - blocks.add("minecraft:" + pasteOptions.getColor().name().toLowerCase() + "_glazed_terracotta"); - blocks.add("minecraft:" + pasteOptions.getColor().name().toLowerCase() + "_stained_glass"); - blocks.add("minecraft:" + pasteOptions.getColor().name().toLowerCase() + "_stained_glass_pane"); - blocks.add("minecraft:" + pasteOptions.getColor().name().toLowerCase() + "_concrete"); - blocks.add("minecraft:" + pasteOptions.getColor().name().toLowerCase() + "_concrete_powder"); - blocks.add("minecraft:" + pasteOptions.getColor().name().toLowerCase() + "_carpet"); + Clipboard clipboard = pasteBuilder.getClipboard(); + if (!pasteBuilder.getMappers().isEmpty()) { + 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)); + } + } + } + } + + AtomicReference pastePoint = new AtomicReference<>(); + if (!pasteBuilder.getPredicates().isEmpty()) { e.setMask(new Mask() { @Override public boolean test(BlockVector3 blockVector3) { - BaseBlock block = clipboard.getFullBlock(blockVector3); - String blockName = block.toString().toLowerCase(); - return blocks.contains(blockName); + BaseBlock block = clipboard.getFullBlock(blockVector3.subtract(pastePoint.get()).add(clipboard.getRegion().getMinimumPoint())); + String blockName = block.getBlockType().toString().toLowerCase(); + for (BiPredicate predicate : pasteBuilder.getPredicates()) { + if (!predicate.test(block, blockName)) return false; + } + return true; + } + + public Mask copy() { + return this; } @Nullable @@ -161,76 +161,34 @@ public class FlatteningWrapper15 implements FlatteningWrapper { public Mask2D toMask2D() { return null; } - - public Mask copy() { - return this; - } }); } ClipboardHolder ch = new ClipboardHolder(clipboard); BlockVector3 dimensions = clipboard.getDimensions(); - BlockVector3 v = BlockVector3.at(pastePoint.getX(), pastePoint.getY(), pastePoint.getZ()); + BlockVector3 v = BlockVector3.at(pasteBuilder.getPastPoint().getX(), pasteBuilder.getPastPoint().getY(), pasteBuilder.getPastPoint().getZ()); BlockVector3 offset = clipboard.getRegion().getMinimumPoint().subtract(clipboard.getOrigin()); - if (pasteOptions.isRotate()) { + 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); } + pastePoint.set(v); - if (pasteOptions.isReset()) { - e.setBlocks((Region) new CuboidRegion(toBlockVector3(pasteOptions.getMinPoint()), toBlockVector3(pasteOptions.getMaxPoint())), Objects.requireNonNull(BlockTypes.AIR).getDefaultState().toBaseBlock()); - if (pasteOptions.getWaterLevel() != 0) { - e.setBlocks((Region) new CuboidRegion(toBlockVector3(pasteOptions.getMinPoint()), toBlockVector3(pasteOptions.getMaxPoint()).withY(pasteOptions.getWaterLevel())), Objects.requireNonNull(BlockTypes.WATER).getDefaultState().toBaseBlock()); + 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(pasteOptions.isIgnoreAir()).build()); + Operations.completeBlindly(ch.createPaste(e).to(v).ignoreAirBlocks(pasteBuilder.isIgnoreAir()).build()); return e; } catch (WorldEditException e) { throw new SecurityException(e.getMessage(), e); } } - @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(); - BaseBlock clay = Objects.requireNonNull(BlockTypes.get(color.name().toLowerCase() + "_terracotta")).getDefaultState().toBaseBlock(); - BaseBlock glazed = Objects.requireNonNull(BlockTypes.get(color.name().toLowerCase() + "_glazed_terracotta")).getDefaultState().toBaseBlock(); - BaseBlock glass = Objects.requireNonNull(BlockTypes.get(color.name().toLowerCase() + "_stained_glass")).getDefaultState().toBaseBlock(); - BaseBlock glassPane = Objects.requireNonNull(BlockTypes.get(color.name().toLowerCase() + "_stained_glass_pane")).getDefaultState().toBaseBlock(); - BaseBlock carpet = Objects.requireNonNull(BlockTypes.get(color.name().toLowerCase() + "_carpet")).getDefaultState().toBaseBlock(); - BaseBlock concrete = Objects.requireNonNull(BlockTypes.get(color.name().toLowerCase() + "_concrete")).getDefaultState().toBaseBlock(); - BaseBlock concretePowder = Objects.requireNonNull(BlockTypes.get(color.name().toLowerCase() + "_concrete_powder")).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(WOOL)) { - clipboard.setBlock(pos, wool); - } else if (block.equals(CLAY)) { - clipboard.setBlock(pos, clay); - } else if (block.equals(GLAZED)) { - clipboard.setBlock(pos, glazed); - } else if (block.equals(GLASS)) { - clipboard.setBlock(pos, glass); - } else if (block.equals(GLASS_PANE)) { - clipboard.setBlock(pos, glassPane); - } else if (block.equals(CARPET)) { - clipboard.setBlock(pos, carpet); - } else if (block.equals(CONCRETE)) { - clipboard.setBlock(pos, concrete); - } else if (block.equals(CONCRETE_POWDER)) { - clipboard.setBlock(pos, concretePowder); - } - } - } - } - } - @Override public boolean backup(Point minPoint, Point maxPoint, File file) { BukkitWorld bukkitWorld = new BukkitWorld(Bukkit.getWorlds().get(0)); @@ -272,19 +230,4 @@ public class FlatteningWrapper15 implements FlatteningWrapper { return ((Waterlogged) data).isWaterlogged(); } - - @Override - public Material getTraceShowMaterial() { - return Material.LIME_CONCRETE; - } - - @Override - public Material getTraceHideMaterial() { - return Material.RED_CONCRETE; - } - - @Override - public Material getTraceXZMaterial() { - return Material.QUARTZ_SLAB; - } } diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/backup/BackupCommand.java b/BauSystem_Main/src/de/steamwar/bausystem/features/backup/BackupCommand.java index 9799b628..38bfe194 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/backup/BackupCommand.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/backup/BackupCommand.java @@ -19,10 +19,15 @@ package de.steamwar.bausystem.features.backup; +import com.sk89q.worldedit.EditSession; import de.steamwar.bausystem.BauSystem; import de.steamwar.bausystem.Permission; +import de.steamwar.bausystem.region.Color; import de.steamwar.bausystem.region.Region; +import de.steamwar.bausystem.region.flags.Flag; +import de.steamwar.bausystem.region.flags.flagvalues.ColorMode; import de.steamwar.bausystem.region.tags.Tag; +import de.steamwar.bausystem.utils.PasteBuilder; import de.steamwar.command.SWCommand; import de.steamwar.command.SWCommandUtils; import de.steamwar.command.TypeMapper; @@ -85,7 +90,14 @@ public class BackupCommand extends SWCommand { BauSystem.MESSAGE.send("BACKUP_LOAD_FAILURE", p); return; } - region.reset(backupFile); + EditSession editSession = new PasteBuilder(new PasteBuilder.FileProvider(backupFile)) + .pastePoint(region.getMinPoint().add(region.getPrototype().getSizeX() / 2, 0, region.getPrototype().getSizeZ() / 2)) + .color(region.getPlain(Flag.COLOR, ColorMode.class).getColor()) + .minPoint(region.getMinPoint()) + .maxPoint(region.getMaxPoint()) + .waterLevel(region.getWaterLevel()) + .run(); + region.remember(editSession); BauSystem.MESSAGE.send("BACKUP_LOAD", p); } diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/region/ColorCommand.java b/BauSystem_Main/src/de/steamwar/bausystem/features/region/ColorCommand.java index 1213a314..543d8727 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/region/ColorCommand.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/region/ColorCommand.java @@ -27,6 +27,7 @@ import de.steamwar.bausystem.region.flags.Flag; import de.steamwar.bausystem.region.flags.flagvalues.ColorMode; import de.steamwar.bausystem.region.utils.RegionExtensionType; import de.steamwar.bausystem.region.utils.RegionType; +import de.steamwar.bausystem.utils.PasteBuilder; import de.steamwar.command.SWCommand; import de.steamwar.command.TypeValidator; import de.steamwar.linkage.Linked; @@ -64,10 +65,14 @@ public class ColorCommand extends SWCommand { } region.set(Flag.COLOR, color); try { - region.reset(null, RegionType.NORMAL, RegionExtensionType.NORMAL, true, true); + PasteBuilder pasteBuilder = new PasteBuilder(new PasteBuilder.FileProvider(region.getResetFile(RegionType.NORMAL))) + .ignoreAir(true) + .onlyColors(true) + .color(color.getColor()); + region.reset(pasteBuilder, RegionType.NORMAL, RegionExtensionType.NORMAL); RegionUtils.message(region, "REGION_REGION_COLORED"); RegionUtils.message(region, "REGION_REGION_COLORED_FAILED"); - } catch (IOException e) { + } catch (SecurityException e) { BauSystem.MESSAGE.send("REGION_REGION_FAILED_COLORED", p); } } diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/region/RegionCommand.java b/BauSystem_Main/src/de/steamwar/bausystem/features/region/RegionCommand.java index 0288fbae..5caf0af3 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/region/RegionCommand.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/region/RegionCommand.java @@ -25,8 +25,11 @@ import de.steamwar.bausystem.features.util.SelectCommand; import de.steamwar.bausystem.region.Prototype; import de.steamwar.bausystem.region.Region; import de.steamwar.bausystem.region.RegionUtils; +import de.steamwar.bausystem.region.flags.Flag; +import de.steamwar.bausystem.region.flags.flagvalues.ColorMode; import de.steamwar.bausystem.region.utils.RegionExtensionType; import de.steamwar.bausystem.region.utils.RegionType; +import de.steamwar.bausystem.utils.PasteBuilder; import de.steamwar.command.PreviousArguments; import de.steamwar.command.SWCommand; import de.steamwar.command.TypeMapper; @@ -99,9 +102,12 @@ public class RegionCommand extends SWCommand { if(checkGlobalRegion(region, p)) return; try { - region.reset(null, RegionType.NORMAL, RegionExtensionType.NORMAL, true, false); + PasteBuilder pasteBuilder = new PasteBuilder(new PasteBuilder.FileProvider(region.getResetFile(RegionType.NORMAL))) + .ignoreAir(true) + .color(region.getPlain(Flag.COLOR, ColorMode.class).getColor()); + region.reset(pasteBuilder, RegionType.NORMAL, RegionExtensionType.NORMAL); RegionUtils.message(region, "REGION_REGION_RESTORED"); - } catch (IOException e) { + } catch (SecurityException e) { BauSystem.MESSAGE.send("REGION_REGION_FAILED_RESTORE", p); Bukkit.getLogger().log(Level.WARNING, "Failed restore", e); } @@ -118,9 +124,12 @@ public class RegionCommand extends SWCommand { } try { - region.reset(node, RegionType.NORMAL, RegionExtensionType.NORMAL, true); + PasteBuilder pasteBuilder = new PasteBuilder(new PasteBuilder.SchematicProvider(node)) + .ignoreAir(true) + .color(region.getPlain(Flag.COLOR, ColorMode.class).getColor()); + region.reset(pasteBuilder, RegionType.NORMAL, RegionExtensionType.NORMAL); RegionUtils.message(region, "REGION_REGION_RESTORED"); - } catch (IOException e) { + } catch (SecurityException e) { BauSystem.MESSAGE.send("REGION_REGION_FAILED_RESTORE", p); Bukkit.getLogger().log(Level.WARNING, "Failed restore", e); } diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/region/ResetCommand.java b/BauSystem_Main/src/de/steamwar/bausystem/features/region/ResetCommand.java index 38e6a3e2..03a22027 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/region/ResetCommand.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/region/ResetCommand.java @@ -25,7 +25,11 @@ import de.steamwar.bausystem.config.BauServer; import de.steamwar.bausystem.region.GlobalRegion; import de.steamwar.bausystem.region.Region; import de.steamwar.bausystem.region.RegionUtils; +import de.steamwar.bausystem.region.flags.Flag; +import de.steamwar.bausystem.region.flags.flagvalues.ColorMode; +import de.steamwar.bausystem.region.utils.RegionExtensionType; import de.steamwar.bausystem.region.utils.RegionType; +import de.steamwar.bausystem.utils.PasteBuilder; import de.steamwar.command.SWCommand; import de.steamwar.command.TypeValidator; import de.steamwar.linkage.Linked; @@ -54,9 +58,11 @@ public class ResetCommand extends SWCommand { Region region = regionCheck(p); if (region == null) return; try { - region.reset(null, RegionType.NORMAL); + PasteBuilder pasteBuilder = new PasteBuilder(new PasteBuilder.FileProvider(region.getResetFile(RegionType.NORMAL))) + .color(region.getPlain(Flag.COLOR, ColorMode.class).getColor()); + region.reset(pasteBuilder, RegionType.NORMAL, RegionExtensionType.NORMAL); RegionUtils.message(region, "REGION_RESET_RESETED"); - } catch (IOException e) { + } catch (SecurityException e) { BauSystem.MESSAGE.send("REGION_RESET_ERROR", p); Bukkit.getLogger().log(Level.WARNING, "Failed testblock", e); } @@ -81,9 +87,11 @@ public class ResetCommand extends SWCommand { return; } try { - region.reset(node, RegionType.NORMAL); + PasteBuilder pasteBuilder = new PasteBuilder(new PasteBuilder.SchematicProvider(node)) + .color(region.getPlain(Flag.COLOR, ColorMode.class).getColor()); + region.reset(pasteBuilder, RegionType.NORMAL, RegionExtensionType.NORMAL); RegionUtils.message(region, "REGION_RESET_RESETED"); - } catch (IOException e) { + } catch (SecurityException e) { BauSystem.MESSAGE.send("REGION_RESET_ERROR", p); Bukkit.getLogger().log(Level.WARNING, "Failed reset", e); } 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 46bfe951..132e7cac 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/region/TestblockCommand.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/region/TestblockCommand.java @@ -24,25 +24,32 @@ import de.steamwar.bausystem.Permission; import de.steamwar.bausystem.config.BauServer; import de.steamwar.bausystem.region.Region; import de.steamwar.bausystem.region.RegionUtils; +import de.steamwar.bausystem.region.flags.Flag; +import de.steamwar.bausystem.region.flags.flagvalues.ColorMode; import de.steamwar.bausystem.region.utils.RegionExtensionType; import de.steamwar.bausystem.region.utils.RegionType; -import de.steamwar.command.*; +import de.steamwar.bausystem.utils.PasteBuilder; +import de.steamwar.command.PreviousArguments; +import de.steamwar.command.SWCommand; +import de.steamwar.command.TypeMapper; +import de.steamwar.command.TypeValidator; import de.steamwar.linkage.Linked; import de.steamwar.linkage.LinkedInstance; -import de.steamwar.command.PreviousArguments; import de.steamwar.sql.Punishment; import de.steamwar.sql.SchematicNode; import de.steamwar.sql.SteamwarUser; +import lombok.Getter; import org.bukkit.Bukkit; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import java.io.IOException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; +import java.util.concurrent.atomic.AtomicReference; +import java.util.function.Consumer; +import java.util.function.Supplier; import java.util.logging.Level; +import java.util.stream.Collectors; @Linked public class TestblockCommand extends SWCommand { @@ -54,42 +61,32 @@ public class TestblockCommand extends SWCommand { super("testblock", "tb", "dummy"); } - @Register(description = "REGION_TB_HELP_RESET") - public void genericTestblockCommand(Player p) { - genericTestblockCommand(p, RegionExtensionType.NORMAL); - } - - @Register(description = "REGION_TB_HELP_RESET_EXTENSION") - public void genericTestblockCommand(@Validator Player p, RegionExtensionType regionExtensionType) { - Region region = regionCheck(p); - if (region == null) return; - try { - region.reset(RegionType.TESTBLOCK, regionExtensionType); - RegionUtils.message(region, "REGION_TB_DONE"); - } catch (IOException e) { - BauSystem.MESSAGE.send("REGION_TB_ERROR", p); - Bukkit.getLogger().log(Level.WARNING, "Failed testblock", e); - } - } - - @Register(description = "REGION_TB_HELP_SCHEMATIC") - public void schematicTestblockCommand(Player p, @Mapper("withPublic") SchematicNode node) { - schematicTestblockCommand(p, node, RegionExtensionType.NORMAL); + @Register + public void schematicTestblockCommand(@Validator Player p, TestblockParameterType... testblockParameterTypes) { + schematicTestblockCommand(p, null, testblockParameterTypes); } @Register - public void schematicTestblockCommand(Player p, RegionExtensionType regionExtensionType, @Mapper("withPublic") SchematicNode node) { - schematicTestblockCommand(p, node, regionExtensionType); + public void schematicTestblockCommand(@Validator Player p, @Mapper("withPublic") SchematicNode node, TestblockParameterType... testblockParameterTypes) { + Set testblockParameterTypesSet = new HashSet<>(Arrays.asList(testblockParameterTypes)); + boolean isExtension = testblockParameterTypesSet.contains(TestblockParameterType.EXTENSION); + boolean isIgnoreAir = testblockParameterTypesSet.contains(TestblockParameterType.IGNORE_AIR); + boolean isOnlyColor = testblockParameterTypesSet.contains(TestblockParameterType.ONLY_COLOR); + boolean replaceTNT = testblockParameterTypesSet.contains(TestblockParameterType.TNT); + boolean replaceWater = testblockParameterTypesSet.contains(TestblockParameterType.WATER); + + resetRegion(p, node, isExtension ? RegionExtensionType.EXTENSION : RegionExtensionType.NORMAL, isIgnoreAir, isOnlyColor, replaceTNT, replaceWater); } - @Register(description = "REGION_TB_HELP_SCHEMATIC_EXTENSION") - public void schematicTestblockCommand(@Validator Player p, @Mapper("withPublic") SchematicNode node, RegionExtensionType regionExtensionType) { + private void resetRegion(Player p, SchematicNode node, RegionExtensionType regionExtensionType, boolean ignoreAir, boolean onlyColors, boolean removeTNT, boolean removeWater) { Region region = regionCheck(p); if (region == null) return; - if(node.isDir()) { - BauSystem.MESSAGE.send("ONLY_SCHEMS", p); - return; + if (node != null) { + if (node.isDir()) { + BauSystem.MESSAGE.send("ONLY_SCHEMS", p); + return; + } } if (!p.getUniqueId().equals(bauServer.getOwner())) { @@ -102,31 +99,67 @@ public class TestblockCommand extends SWCommand { } try { - region.reset(node, RegionType.TESTBLOCK, regionExtensionType); + PasteBuilder.ClipboardProvider clipboardProvider = node == null ? new PasteBuilder.FileProvider(region.getResetFile(RegionType.TESTBLOCK)) : new PasteBuilder.SchematicProvider(node); + PasteBuilder pasteBuilder = new PasteBuilder(clipboardProvider) + .ignoreAir(ignoreAir) + .onlyColors(onlyColors) + .removeTNT(removeTNT) + .removeWater(removeWater) + .color(region.getPlain(Flag.COLOR, ColorMode.class).getColor()); + region.reset(pasteBuilder, RegionType.TESTBLOCK, regionExtensionType); RegionUtils.message(region, "REGION_TB_DONE"); - } catch (IOException e) { + } catch (SecurityException e) { BauSystem.MESSAGE.send("REGION_TB_ERROR", p); Bukkit.getLogger().log(Level.WARNING, "Failed testblock", e); } } - @ClassMapper(value = RegionExtensionType.class, local = true) - private TypeMapper regionExtensionTypeTypeMapper() { - Map showModeParameterTypesMap = new HashMap<>(); - showModeParameterTypesMap.put("-normal", RegionExtensionType.NORMAL); - showModeParameterTypesMap.put("-n", RegionExtensionType.NORMAL); - showModeParameterTypesMap.put("-extension", RegionExtensionType.EXTENSION); - showModeParameterTypesMap.put("-e", RegionExtensionType.EXTENSION); + @ClassMapper(value = TestblockParameterType.class, local = true) + public TypeMapper testblockParameterTypeMapper() { + Map> testblockParameterTypeListMap = new EnumMap<>(TestblockParameterType.class); + for (TestblockParameterType value : TestblockParameterType.values()) { + testblockParameterTypeListMap.put(value, value.getTabCompletes()); + } - List tabCompletes = new ArrayList<>(showModeParameterTypesMap.keySet()); - return SWCommandUtils.createMapper(s -> showModeParameterTypesMap.getOrDefault(s, null), s -> tabCompletes); + Map testblockParameterTypesMap = new HashMap<>(); + testblockParameterTypeListMap.forEach((k, v) -> v.forEach(s -> testblockParameterTypesMap.put(s, k))); + + return new TypeMapper() { + @Override + public TestblockParameterType map(CommandSender commandSender, PreviousArguments previousArguments, String s) { + return testblockParameterTypesMap.get(s); + } + + @Override + public List tabCompletes(CommandSender commandSender, PreviousArguments previousArguments, String s) { + Set testblockParameterTypeSet = new HashSet<>(); + previousArguments.getAll(TestblockParameterType.class).forEach(showModeType -> { + testblockParameterTypeSet.addAll(Arrays.asList(showModeType.getRemoved().get())); + }); + Arrays.stream(previousArguments.userArgs).map(testblockParameterTypesMap::get).forEach(testblockParameterTypeSet::add); + testblockParameterTypeSet.remove(null); + + Set removed = testblockParameterTypeSet.stream() + .map(TestblockParameterType::getRemoved) + .map(Supplier::get) + .flatMap(Arrays::stream) + .collect(Collectors.toSet()); + + List tabCompletes = new ArrayList<>(); + for (Map.Entry> entry : testblockParameterTypeListMap.entrySet()) { + if (removed.contains(entry.getKey()) || testblockParameterTypeSet.contains(entry.getKey())) { + continue; + } + tabCompletes.addAll(entry.getValue()); + } + return tabCompletes; + } + }; } @ClassValidator(value = Player.class, local = true) public TypeValidator validator() { - return (commandSender, player, messageSender) -> { - return !messageSender.send(!Permission.hasPermission(player, Permission.WORLD), "REGION_TB_NO_PERMS"); - }; + return (commandSender, player, messageSender) -> !messageSender.send(!Permission.hasPermission(player, Permission.WORLD), "REGION_TB_NO_PERMS"); } private Region regionCheck(Player player) { @@ -151,11 +184,74 @@ public class TestblockCommand extends SWCommand { @Override public SchematicNode map(CommandSender commandSender, PreviousArguments previousArguments, String s) { SchematicNode node = SchematicNode.getNodeFromPath(SteamwarUser.get(((Player) commandSender).getUniqueId()), s); - if(node == null) { + if (node == null) { node = SchematicNode.getNodeFromPath(SteamwarUser.get(0), s); } return node; } }; } + + public static class TestblockParameter { + private boolean water = false; + private boolean tnt = false; + private boolean extension = false; + private boolean onlyColor = false; + + private boolean ignoreAir = false; + + public void enableWater() { + this.water = true; + } + + public void enableTNT() { + this.tnt = true; + } + + public void enableExtension() { + this.extension = true; + } + + public void enableOnlyColor() { + this.onlyColor = true; + } + + public void enableIgnoreAir() { + this.ignoreAir = true; + } + } + + public enum TestblockParameterType { + EXTENSION(TestblockParameter::enableExtension, Arrays.asList("-e", "-extension")), + TNT(TestblockParameter::enableTNT, Arrays.asList("-t", "-tnt")), + WATER(TestblockParameter::enableWater, Arrays.asList("-w", "-water")), + IGNORE_AIR(TestblockParameter::enableIgnoreAir, Arrays.asList("-ig", "-ignore_air")), + ONLY_COLOR(TestblockParameter::enableOnlyColor, Arrays.asList("-o", "-color", "-only_color")); + + @Getter + private final Consumer testblockParameterConsumer; + + @Getter + private List tabCompletes; + + @Getter + private final Supplier removed; + private AtomicReference cached = new AtomicReference<>(); + + TestblockParameterType(Consumer testblockParameterConsumer, List tabCompletes, String... removed) { + this.testblockParameterConsumer = testblockParameterConsumer; + this.tabCompletes = tabCompletes; + this.removed = () -> { + if (cached.get() == null) { + TestblockParameterType[] showModeParameterTypes = new TestblockParameterType[removed.length]; + for (int i = 0; i < removed.length; i++) { + showModeParameterTypes[i] = TestblockParameterType.valueOf(removed[i]); + } + cached.set(showModeParameterTypes); + return showModeParameterTypes; + } + return cached.get(); + }; + } + } } diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/region/items/TestblockBauGuiItem.java b/BauSystem_Main/src/de/steamwar/bausystem/features/region/items/TestblockBauGuiItem.java index 2b3b863a..7b0f25e0 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/region/items/TestblockBauGuiItem.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/region/items/TestblockBauGuiItem.java @@ -51,7 +51,7 @@ public class TestblockBauGuiItem extends BauGuiItem { public boolean click(ClickType click, Player p) { if (click == ClickType.LEFT) { p.closeInventory(); - testblockCommand.genericTestblockCommand(p); + testblockCommand.schematicTestblockCommand(p); } else { SchematicSelector selector = new SchematicSelector(p, SchematicSelector.selectSchematic(), node -> { p.closeInventory(); diff --git a/BauSystem_Main/src/de/steamwar/bausystem/region/PasteOptions.java b/BauSystem_Main/src/de/steamwar/bausystem/region/PasteOptions.java deleted file mode 100644 index e28a02d8..00000000 --- a/BauSystem_Main/src/de/steamwar/bausystem/region/PasteOptions.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * This file is a part of the SteamWar software. - * - * Copyright (C) 2021 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.region; - -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Getter; - -@Getter -@Builder -@AllArgsConstructor -public class PasteOptions { - - /** - * Used in 1.15 - */ - private final boolean rotate; - - /** - * Used in 1.15 - */ - private final boolean ignoreAir; - - /** - * Used in 1.15 - */ - private final Color color; - - /** - * Used in 1.15 - */ - private final boolean onlyColors; - - /** - * Used in 1.15 - */ - private final boolean reset; - - /** - * Used in 1.15 - */ - private final Point minPoint; - - /** - * Used in 1.15 - */ - private final Point maxPoint; - - /** - * Used in 1.15 - */ - private final int waterLevel; -} \ No newline at end of file diff --git a/BauSystem_Main/src/de/steamwar/bausystem/region/Region.java b/BauSystem_Main/src/de/steamwar/bausystem/region/Region.java index 2d3fdc04..dd234713 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/region/Region.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/region/Region.java @@ -22,19 +22,17 @@ package de.steamwar.bausystem.region; import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.bukkit.BukkitWorld; -import com.sk89q.worldedit.extent.clipboard.Clipboard; import de.steamwar.bausystem.BauSystem; import de.steamwar.bausystem.region.flags.Flag; -import de.steamwar.bausystem.region.flags.flagvalues.ColorMode; import de.steamwar.bausystem.region.flags.flagvalues.TNTMode; import de.steamwar.bausystem.region.tags.Tag; import de.steamwar.bausystem.region.utils.RegionExtensionType; import de.steamwar.bausystem.region.utils.RegionType; import de.steamwar.bausystem.shared.SizedStack; import de.steamwar.bausystem.utils.FlatteningWrapper; +import de.steamwar.bausystem.utils.PasteBuilder; import de.steamwar.core.Core; -import de.steamwar.sql.SchematicData; -import de.steamwar.sql.SchematicNode; +import de.steamwar.sql.SchematicType; import lombok.AccessLevel; import lombok.Getter; import lombok.NonNull; @@ -45,7 +43,6 @@ import yapion.hierarchy.types.YAPIONType; import yapion.hierarchy.types.YAPIONValue; import java.io.File; -import java.io.IOException; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.*; @@ -53,8 +50,6 @@ import java.util.function.ObjIntConsumer; import java.util.function.Predicate; import java.util.stream.Collectors; -import static de.steamwar.bausystem.region.RegionUtils.paste; - @Getter public class Region { @@ -413,33 +408,22 @@ public class Region { } } - public void reset(RegionType regionType) throws IOException { - reset(null, regionType); + public File getResetFile(RegionType regionType) { + if (!hasReset(regionType)) { + return null; + } + switch (regionType) { + case TESTBLOCK: + return prototype.getSkinMap().get(skin).getTestblockSchematicFile(); + case BUILD: + return prototype.getSkinMap().get(skin).getBuildSchematicFile(); + default: + case NORMAL: + return prototype.getSkinMap().get(skin).getSchematicFile(); + } } - public void reset(SchematicNode schematic, RegionType regionType) throws IOException { - reset(schematic, regionType, RegionExtensionType.NORMAL, false); - } - - public void reset(RegionType regionType, RegionExtensionType regionExtensionType) throws IOException { - reset(null, regionType, regionExtensionType, false); - } - - public void reset(SchematicNode schematic, RegionType regionType, RegionExtensionType regionExtensionType) throws IOException { - reset(schematic, regionType, regionExtensionType, false); - } - - public void reset(File file) { - EditSession editSession = paste(file, minPoint.add(prototype.getSizeX() / 2, 0, prototype.getSizeZ() / 2), new PasteOptions(false, false, Color.YELLOW, false, false, getMinPoint(RegionType.NORMAL, RegionExtensionType.NORMAL), getMaxPoint(RegionType.NORMAL, RegionExtensionType.NORMAL), waterLevel)); - initSessions(); - undoSessions.push(editSession); - } - - public void reset(SchematicNode schematic, RegionType regionType, RegionExtensionType regionExtensionType, boolean ignoreAir) throws IOException { - reset(schematic, regionType, regionExtensionType, ignoreAir, false); - } - - public void reset(SchematicNode schematic, RegionType regionType, RegionExtensionType regionExtensionType, boolean ignoreAir, boolean onlyColors) throws IOException { + public void reset(PasteBuilder pasteBuilder, RegionType regionType, RegionExtensionType regionExtensionType) { if (!hasReset(regionType)) { return; } @@ -447,54 +431,50 @@ public class Region { regionExtensionType = RegionExtensionType.NORMAL; } - PasteOptions pasteOptions = new PasteOptions((schematic != null && (schematic.getSchemtype().fightType() || schematic.getSchemtype().check())), ignoreAir, getPlain(Flag.COLOR, ColorMode.class).getColor(), onlyColors, regionExtensionType == RegionExtensionType.EXTENSION, getMinPoint(regionType, regionExtensionType), getMaxPoint(regionType, regionExtensionType), waterLevel); + pasteBuilder.reset(regionExtensionType == RegionExtensionType.EXTENSION) + .minPoint(getMinPoint(regionType, regionExtensionType)) + .maxPoint(getMaxPoint(regionType, regionExtensionType)) + .waterLevel(waterLevel); + if (pasteBuilder.getClipboardProvider().is(PasteBuilder.SchematicProvider.class)) { + SchematicType schematicType = pasteBuilder.getClipboardProvider().as(PasteBuilder.SchematicProvider.class).getSchematic().getSchemtype(); + pasteBuilder.rotate(schematicType.fightType() || schematicType.check()); + } - Point pastePoint; - File tempFile = null; - Clipboard clipboard = null; switch (regionType) { case BUILD: - pastePoint = minPointBuild.add(prototype.getBuild().getSizeX() / 2, 0, prototype.getBuild().getSizeZ() / 2); - if (schematic == null) { - tempFile = prototype.getSkinMap().get(skin).getBuildSchematicFile(); - } + pasteBuilder.pastePoint(minPointBuild.add(prototype.getBuild().getSizeX() / 2, 0, prototype.getBuild().getSizeZ() / 2)); break; case TESTBLOCK: - pastePoint = minPointTestblock.add(prototype.getTestblock().getSizeX() / 2, 0, 0); - if (schematic == null) { - tempFile = prototype.getSkinMap().get(skin).getTestblockSchematicFile(); + Point pastePoint = minPointTestblock.add(prototype.getTestblock().getSizeX() / 2, 0, 0); + if (!pasteBuilder.getClipboardProvider().is(PasteBuilder.SchematicProvider.class)) { pastePoint = pastePoint.add(0, 0, prototype.getTestblock().getSizeZ() / 2); } else { - clipboard = new SchematicData(schematic).load(); - int dz = Math.abs(clipboard.getOrigin().getZ() - clipboard.getMinimumPoint().getZ()); + int dz = Math.abs(pasteBuilder.getClipboard().getOrigin().getZ() - pasteBuilder.getClipboard().getMinimumPoint().getZ()); if (dz < 2 || dz > prototype.getTestblock().getSizeZ()) { pastePoint = pastePoint.add(0, 0, prototype.getTestblock().getSizeZ() / 2); - } else if (clipboard.getDimensions().getZ() != prototype.getTestblock().getSizeZ()) { - pastePoint = pastePoint.add(0, 0, clipboard.getDimensions().getZ() / 2 - (clipboard.getOrigin().getZ() - clipboard.getMinimumPoint().getZ()) - 1); + } else if (pasteBuilder.getClipboard().getDimensions().getZ() != prototype.getTestblock().getSizeZ()) { + pastePoint = pastePoint.add(0, 0, pasteBuilder.getClipboard().getDimensions().getZ() / 2 - (pasteBuilder.getClipboard().getOrigin().getZ() - pasteBuilder.getClipboard().getMinimumPoint().getZ()) - 1); } else { pastePoint = pastePoint.add(0, 0, prototype.getTestblock().getSizeZ() / 2); } - if (schematic.getSchemtype().getKuerzel().equalsIgnoreCase("wg")) { + SchematicType schematicType = pasteBuilder.getClipboardProvider().as(PasteBuilder.SchematicProvider.class).getSchematic().getSchemtype(); + if (schematicType.getKuerzel().equalsIgnoreCase("wg")) { pastePoint = pastePoint.add(0, 0, 1); } } + pasteBuilder.pastePoint(pastePoint); break; default: case NORMAL: - pastePoint = minPoint.add(prototype.getSizeX() / 2, 0, prototype.getSizeZ() / 2); - if (schematic == null) { - tempFile = prototype.getSkinMap().get(skin).getSchematicFile(); - } + pasteBuilder.pastePoint(minPoint.add(prototype.getSizeX() / 2, 0, prototype.getSizeZ() / 2)); break; } - EditSession editSession = null; - if (schematic != null) { - editSession = paste(clipboard != null ? clipboard : new SchematicData(schematic).load(), pastePoint, pasteOptions); - } else { - editSession = paste(tempFile, pastePoint, pasteOptions); - } + initSessions(); + undoSessions.push(pasteBuilder.run()); + } + public void remember(EditSession editSession) { initSessions(); undoSessions.push(editSession); } diff --git a/BauSystem_Main/src/de/steamwar/bausystem/region/RegionUtils.java b/BauSystem_Main/src/de/steamwar/bausystem/region/RegionUtils.java index 3f81b60a..e30c3ed9 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/region/RegionUtils.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/region/RegionUtils.java @@ -81,14 +81,6 @@ public class RegionUtils { }); } - static EditSession paste(File file, Point pastePoint, PasteOptions pasteOptions) { - return FlatteningWrapper.impl.paste(file, pastePoint, pasteOptions); - } - - static EditSession paste(Clipboard clipboard, Point pastePoint, PasteOptions pasteOptions) { - return FlatteningWrapper.impl.paste(clipboard, pastePoint, pasteOptions); - } - static void save(Region region) { if (region.getPrototype() != null) { region.regionData.add("prototype", region.getPrototype().getName()); diff --git a/BauSystem_Main/src/de/steamwar/bausystem/utils/FlatteningWrapper.java b/BauSystem_Main/src/de/steamwar/bausystem/utils/FlatteningWrapper.java index 430bfe90..aef0b302 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/utils/FlatteningWrapper.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/utils/FlatteningWrapper.java @@ -20,11 +20,8 @@ package de.steamwar.bausystem.utils; import com.sk89q.worldedit.EditSession; -import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.extent.clipboard.Clipboard; import de.steamwar.bausystem.BauSystem; -import de.steamwar.bausystem.region.Color; -import de.steamwar.bausystem.region.PasteOptions; import de.steamwar.bausystem.region.Point; import de.steamwar.core.VersionDependent; import org.bukkit.Material; @@ -46,14 +43,10 @@ public interface FlatteningWrapper { boolean isWorldEditCommand(String command); void setSelection(Player p, Point minPoint, Point maxPoint); - EditSession paste(File file, Point pastePoint, PasteOptions pasteOptions); - EditSession paste(Clipboard clipboard, Point pastePoint, PasteOptions pasteOptions); - void changeColor(Clipboard clipboard, Color color) throws WorldEditException; + Clipboard loadSchematic(File file); + EditSession paste(PasteBuilder pasteBuilder); + boolean backup(Point minPoint, Point maxPoint, File file); boolean inWater(World world, Vector tntPosition); - - Material getTraceShowMaterial(); - Material getTraceHideMaterial(); - Material getTraceXZMaterial(); } 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..3dddc008 --- /dev/null +++ b/BauSystem_Main/src/de/steamwar/bausystem/utils/PasteBuilder.java @@ -0,0 +1,262 @@ +/* + * 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.function.pattern.WaterloggedRemover; +import com.sk89q.worldedit.math.BlockVector3; +import com.sk89q.worldedit.world.block.BaseBlock; +import com.sk89q.worldedit.world.block.BlockTypes; +import de.steamwar.bausystem.region.Color; +import de.steamwar.bausystem.region.Point; +import de.steamwar.sql.SchematicData; +import de.steamwar.sql.SchematicNode; +import lombok.Getter; +import lombok.NonNull; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.function.BiConsumer; +import java.util.function.BiPredicate; + +@Getter +public class PasteBuilder { + + private final ClipboardProvider clipboardProvider; + 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(@NonNull ClipboardProvider clipboardProvider) { + this.clipboardProvider = clipboardProvider; + } + + public PasteBuilder pastePoint(Point point) { + this.pastPoint = point; + return this; + } + + public PasteBuilder rotate(boolean rotate) { + this.rotate = rotate; + return this; + } + + public PasteBuilder ignoreAir(boolean ignoreAir) { + this.ignoreAir = ignoreAir; + return this; + } + + public PasteBuilder reset(boolean reset) { + this.reset = reset; + 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 PasteBuilder color(Color color) { + if (color == Color.PINK) return this; + + BaseBlock WOOL = Objects.requireNonNull(BlockTypes.PINK_WOOL).getDefaultState().toBaseBlock(); + BaseBlock CLAY = Objects.requireNonNull(BlockTypes.PINK_TERRACOTTA).getDefaultState().toBaseBlock(); + BaseBlock GLAZED = Objects.requireNonNull(BlockTypes.PINK_GLAZED_TERRACOTTA).getDefaultState().toBaseBlock(); + BaseBlock GLASS = Objects.requireNonNull(BlockTypes.PINK_STAINED_GLASS).getDefaultState().toBaseBlock(); + BaseBlock GLASS_PANE = Objects.requireNonNull(BlockTypes.PINK_STAINED_GLASS_PANE).getDefaultState().toBaseBlock(); + BaseBlock CONCRETE = Objects.requireNonNull(BlockTypes.PINK_CONCRETE).getDefaultState().toBaseBlock(); + BaseBlock CONCRETE_POWDER = Objects.requireNonNull(BlockTypes.PINK_CONCRETE_POWDER).getDefaultState().toBaseBlock(); + BaseBlock CARPET = Objects.requireNonNull(BlockTypes.PINK_CARPET).getDefaultState().toBaseBlock(); + + BaseBlock wool = Objects.requireNonNull(BlockTypes.get(color.name().toLowerCase() + "_wool")).getDefaultState().toBaseBlock(); + BaseBlock clay = Objects.requireNonNull(BlockTypes.get(color.name().toLowerCase() + "_terracotta")).getDefaultState().toBaseBlock(); + BaseBlock glazed = Objects.requireNonNull(BlockTypes.get(color.name().toLowerCase() + "_glazed_terracotta")).getDefaultState().toBaseBlock(); + BaseBlock glass = Objects.requireNonNull(BlockTypes.get(color.name().toLowerCase() + "_stained_glass")).getDefaultState().toBaseBlock(); + BaseBlock glassPane = Objects.requireNonNull(BlockTypes.get(color.name().toLowerCase() + "_stained_glass_pane")).getDefaultState().toBaseBlock(); + BaseBlock carpet = Objects.requireNonNull(BlockTypes.get(color.name().toLowerCase() + "_carpet")).getDefaultState().toBaseBlock(); + BaseBlock concrete = Objects.requireNonNull(BlockTypes.get(color.name().toLowerCase() + "_concrete")).getDefaultState().toBaseBlock(); + BaseBlock concretePowder = Objects.requireNonNull(BlockTypes.get(color.name().toLowerCase() + "_concrete_powder")).getDefaultState().toBaseBlock(); + + return map((clipboard, blockVector3) -> { + BaseBlock block = clipboard.getFullBlock(blockVector3); + if (block.equals(WOOL)) { + clipboard.setBlock(blockVector3, wool); + } else if (block.equals(CLAY)) { + clipboard.setBlock(blockVector3, clay); + } else if (block.equals(GLAZED)) { + clipboard.setBlock(blockVector3, glazed); + } else if (block.equals(GLASS)) { + clipboard.setBlock(blockVector3, glass); + } else if (block.equals(GLASS_PANE)) { + clipboard.setBlock(blockVector3, glassPane); + } else if (block.equals(CARPET)) { + clipboard.setBlock(blockVector3, carpet); + } else if (block.equals(CONCRETE)) { + clipboard.setBlock(blockVector3, concrete); + } else if (block.equals(CONCRETE_POWDER)) { + clipboard.setBlock(blockVector3, concretePowder); + } + }); + } + + public PasteBuilder onlyColors(boolean onlyColors) { + if (!onlyColors) return this; + return only((baseBlock, s) -> { + return s.endsWith("_wool") || s.endsWith("_terracotta") || s.endsWith("_glazed_terracotta") || s.endsWith("_stained_glass") || s.endsWith("_stained_glass_pane") || s.endsWith("_carpet") || s.endsWith("_concrete") || s.endsWith("_concrete_powder"); + }); + } + + public PasteBuilder removeTNT(boolean removeTNT) { + if (!removeTNT) return this; + BaseBlock tnt = Objects.requireNonNull(BlockTypes.get("tnt")).getDefaultState().toBaseBlock(); + BaseBlock air = Objects.requireNonNull(BlockTypes.get("air")).getDefaultState().toBaseBlock(); + + return map((clipboard, blockVector3) -> { + BaseBlock baseBlock = clipboard.getFullBlock(blockVector3); + if (baseBlock.equals(tnt)) { + clipboard.setBlock(blockVector3, air); + } + }); + } + + public PasteBuilder removeWater(boolean removeWater) { + if (!removeWater) return this; + BaseBlock water = Objects.requireNonNull(BlockTypes.get("water")).getDefaultState().toBaseBlock(); + BaseBlock air = Objects.requireNonNull(BlockTypes.get("air")).getDefaultState().toBaseBlock(); + WaterloggedRemover waterloggedRemover = new WaterloggedRemover(getClipboard()); + + return map((clipboard, blockVector3) -> { + BaseBlock baseBlock = clipboard.getFullBlock(blockVector3); + if (baseBlock.equals(water)) { + clipboard.setBlock(blockVector3, air); + return; + } + String blockName = clipboard.getFullBlock(blockVector3).getBlockType().getName(); + if (blockName.equals("Water")) { + clipboard.setBlock(blockVector3, air); + return; + } + clipboard.setBlock(blockVector3, waterloggedRemover.applyBlock(blockVector3)); + }); + } + + public Clipboard getClipboard() { + return clipboardProvider.getClipboard(); + } + + public EditSession run() { + if (pastPoint == null) { + throw new IllegalStateException("pastePoint is null"); + } + return FlatteningWrapper.impl.paste(this); + } + + public interface ClipboardProvider { + Clipboard getClipboard(); + + default boolean is(Class clazz) { + return clazz.isInstance(this); + } + + default T as(Class clazz) { + return clazz.cast(this); + } + } + + @Getter + public static class FileProvider implements ClipboardProvider { + private final File file; + private final Clipboard clipboard; + + public FileProvider(File file) { + this.file = file; + this.clipboard = FlatteningWrapper.impl.loadSchematic(file); + } + + @Override + public Clipboard getClipboard() { + return clipboard; + } + } + + @Getter + public static class SchematicProvider implements ClipboardProvider { + private final SchematicNode schematic; + private final Clipboard clipboard; + + public SchematicProvider(SchematicNode schematic) { + this.schematic = schematic; + try { + this.clipboard = new SchematicData(schematic).load(); + } catch (IOException e) { + throw new SecurityException(e); + } + } + + @Override + public Clipboard getClipboard() { + return clipboard; + } + } + + @Getter + public static class ClipboardProviderImpl implements ClipboardProvider { + private final Clipboard clipboard; + + public ClipboardProviderImpl(Clipboard clipboard) { + this.clipboard = clipboard; + } + + @Override + public Clipboard getClipboard() { + return clipboard; + } + } +}