diff --git a/BauSystem_Main/src/BauSystem.properties b/BauSystem_Main/src/BauSystem.properties
index 5d1b2f0c..3f2e08af 100644
--- a/BauSystem_Main/src/BauSystem.properties
+++ b/BauSystem_Main/src/BauSystem.properties
@@ -517,4 +517,10 @@ LOCK_SCHEM_LOCKED=§e{0} §7von §e{1} §7wurde von §e{2} §7auf §eNORMAL §7z
LOCK_SCHEM_HELP=§8/§eschemlock §8[§7Owner§8] [§7Schematic§8] [§7Grund§8] - §7Sperre eine Schematic
AFK_KICK_MESSAGE=§cAuf diesem Server ist seit 5 Minuten nichts passiert.
-AFK_WARNING_MESSAGE=§cDieser Server wird bei weiterer Inaktivität in einer Minute gestoppt
\ No newline at end of file
+AFK_WARNING_MESSAGE=§cDieser Server wird bei weiterer Inaktivität in einer Minute gestoppt
+
+# Panzern
+PANZERN_HELP = §8/§epanzern §8[§7Block§8] §8[§7Slab§8] §8- §7Panzer deine WorldEdit Auswahl
+PANZERN_NO_PERM = §cDu darfst hier nicht das Panzern System verwenden
+PANZERN_PROGRESS = §e{0} §7Blöcke übrig
+PANZERN_DONE = §aZuende gepanzert
\ No newline at end of file
diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/panzern/Panzern.java b/BauSystem_Main/src/de/steamwar/bausystem/features/panzern/Panzern.java
new file mode 100644
index 00000000..655aa640
--- /dev/null
+++ b/BauSystem_Main/src/de/steamwar/bausystem/features/panzern/Panzern.java
@@ -0,0 +1,166 @@
+/*
+ * 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.features.panzern;
+
+import org.bukkit.Location;
+import org.bukkit.Material;
+import org.bukkit.World;
+import org.bukkit.block.Block;
+import org.bukkit.block.BlockFace;
+import org.bukkit.block.data.Bisected;
+import org.bukkit.block.data.Directional;
+import org.bukkit.block.data.type.Stairs;
+
+import java.util.HashSet;
+import java.util.Set;
+
+public class Panzern {
+
+ private static final BlockFace[] BLOCK_FACES = new BlockFace[]{BlockFace.NORTH, BlockFace.SOUTH, BlockFace.EAST, BlockFace.WEST, BlockFace.UP, BlockFace.DOWN};
+
+ private Set current = new HashSet<>();
+ private Set emptyBlocks = new HashSet<>();
+
+ private World world;
+ private Location pos1;
+ private Location pos2;
+ private Material blockMaterial;
+ private Material slabMaterial;
+
+ public Panzern(Location pos1, Location pos2, Material blockMaterial, Material slabMaterial) {
+ this.world = pos1.getWorld();
+ this.pos1 = new Location(world, Math.min(pos1.getBlockX(), pos2.getBlockX()), Math.min(pos1.getBlockY(), pos2.getBlockY()), Math.min(pos1.getBlockZ(), pos2.getBlockZ()));
+ this.pos2 = new Location(world, Math.max(pos1.getBlockX(), pos2.getBlockX()), Math.max(pos1.getBlockY(), pos2.getBlockY()), Math.max(pos1.getBlockZ(), pos2.getBlockZ()));
+ current.add(this.pos1);
+ current.add(this.pos2);
+ this.blockMaterial = blockMaterial;
+ this.slabMaterial = slabMaterial;
+ }
+
+ public boolean hasNext() {
+ return !current.isEmpty();
+ }
+
+ public void next() {
+ Location toCheck = current.iterator().next();
+ current.remove(toCheck);
+
+ Set adjacent = new HashSet<>();
+ boolean hasRedstone = false;
+ boolean belowRedstone = false;
+ boolean belowCarpet = false;
+ boolean adjacentPiston = false;
+ boolean adjacentSlime = false;
+ for (BlockFace blockFace : BLOCK_FACES) {
+ Location now = toCheck.clone().add(blockFace.getModX(), blockFace.getModY(), blockFace.getModZ());
+ if (inRegion(now)) {
+ adjacent.add(now);
+ }
+ Block block = world.getBlockAt(now);
+ if (block.getType() == Material.SLIME_BLOCK || block.getType() == Material.HONEY_BLOCK) {
+ adjacentSlime = true;
+ }
+ if (block.getType() == Material.PISTON || block.getType() == Material.STICKY_PISTON) {
+ Directional directional = (Directional) block.getBlockData();
+ if (directional.getFacing() == blockFace.getOppositeFace()) {
+ adjacentPiston = true;
+ }
+ }
+ if (blockFace != BlockFace.UP && blockFace != BlockFace.DOWN) {
+ hasRedstone |= block.getType() == Material.REDSTONE_WIRE;
+ }
+ if (blockFace == BlockFace.DOWN) {
+ belowRedstone |= block.getType() == Material.REDSTONE_WIRE;
+ belowCarpet |= block.getType().name().contains("CARPET");
+ }
+ if (blockFace == BlockFace.DOWN && stairCheck(now)) {
+ belowCarpet = true;
+ }
+ now = toCheck.clone().add(blockFace.getModX() * 2, blockFace.getModY() * 2, blockFace.getModZ() * 2);
+ Block blockOuter = world.getBlockAt(now);
+ if (blockFace == BlockFace.DOWN && stairCheck(now)) {
+ belowCarpet = true;
+ }
+ if (blockFace != BlockFace.DOWN && blockFace != BlockFace.UP) {
+ now = toCheck.clone().add(blockFace.getModX(), -2, blockFace.getModZ());
+ Block blockOuterOther = world.getBlockAt(now);
+ if (stairCheck(now)) {
+ Stairs stairs = (Stairs) blockOuterOther.getBlockData();
+ if (stairs.getFacing() == blockFace) {
+ belowCarpet = true;
+ }
+ }
+ }
+ if (block.getType().isAir()) {
+ continue;
+ }
+ if (blockOuter.getType() == Material.PISTON || blockOuter.getType() == Material.STICKY_PISTON) {
+ Directional directional = (Directional) blockOuter.getBlockData();
+ if (directional.getFacing() == blockFace.getOppositeFace()) {
+ adjacentPiston = true;
+ }
+ }
+
+ }
+ current.addAll(adjacent);
+
+ if (belowCarpet || adjacentPiston) {
+ emptyBlocks.add(toCheck);
+ return;
+ }
+ if (adjacentSlime) {
+ world.getBlockAt(toCheck).setType(Material.JUKEBOX);
+ } else if (belowRedstone && hasRedstone) {
+ world.getBlockAt(toCheck).setType(slabMaterial);
+ } else {
+ world.getBlockAt(toCheck).setType(blockMaterial);
+ }
+ }
+
+ private boolean stairCheck(Location location) {
+ Block block = world.getBlockAt(location);
+ if (block.getBlockData() instanceof Stairs) {
+ Stairs stairs = (Stairs) block.getBlockData();
+ return stairs.getHalf() == Bisected.Half.BOTTOM;
+ }
+ return false;
+ }
+
+ private boolean inRegion(Location location) {
+ if (location.getBlockX() >= pos1.getBlockX()) {
+ if (location.getBlockY() >= pos1.getBlockY()) {
+ if (location.getBlockZ() >= pos1.getBlockZ()) {
+ if (location.getBlockX() <= pos2.getBlockX()) {
+ if (location.getBlockY() <= pos2.getBlockY()) {
+ if (location.getBlockZ() <= pos2.getBlockZ()) {
+ return world.getBlockAt(location).getType().isAir() && !emptyBlocks.contains(location);
+ }
+ }
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ public int blocksLeft() {
+ return current.size();
+ }
+}
diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/panzern/PanzernCommand.java b/BauSystem_Main/src/de/steamwar/bausystem/features/panzern/PanzernCommand.java
new file mode 100644
index 00000000..96b008ba
--- /dev/null
+++ b/BauSystem_Main/src/de/steamwar/bausystem/features/panzern/PanzernCommand.java
@@ -0,0 +1,105 @@
+/*
+ * 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.features.panzern;
+
+import com.sk89q.worldedit.IncompleteRegionException;
+import com.sk89q.worldedit.WorldEdit;
+import com.sk89q.worldedit.bukkit.BukkitAdapter;
+import com.sk89q.worldedit.math.BlockVector3;
+import com.sk89q.worldedit.regions.RegionSelector;
+import de.steamwar.bausystem.BauSystem;
+import de.steamwar.bausystem.Permission;
+import de.steamwar.bausystem.SWUtils;
+import de.steamwar.bausystem.linkage.LinkageType;
+import de.steamwar.bausystem.linkage.Linked;
+import de.steamwar.bausystem.shared.Pair;
+import de.steamwar.command.SWCommand;
+import org.bukkit.Location;
+import org.bukkit.Material;
+import org.bukkit.World;
+import org.bukkit.entity.Player;
+import org.bukkit.scheduler.BukkitRunnable;
+
+@Linked(LinkageType.COMMAND)
+public class PanzernCommand extends SWCommand {
+
+ public PanzernCommand() {
+ super("panzern", "panzersklave");
+ }
+
+ private boolean permissionCheck(Player player, Permission permission) {
+ if (Permission.hasPermission(player, permission)) {
+ return true;
+ }
+ BauSystem.MESSAGE.send("PANZERN_NO_PERM", player);
+ return false;
+ }
+
+ @Register
+ public void genericHelp(Player player, String... args) {
+ BauSystem.MESSAGE.send("COMMAND_HELP_HEAD", player, "panzern");
+ BauSystem.MESSAGE.send("PANZERN_HELP", player);
+ }
+
+ @Register
+ public void panzerSelection(Player player, Material blockMaterial, Material slabMaterial) {
+ if (!permissionCheck(player, Permission.WORLDEDIT)) {
+ return;
+ }
+ Pair selection = getSelection(player);
+ if (selection == null) {
+ return;
+ }
+ Panzern panzern = new Panzern(selection.getKey(), selection.getValue(), blockMaterial, slabMaterial);
+ new BukkitRunnable() {
+ @Override
+ public void run() {
+ SWUtils.sendToActionbar(player, BauSystem.MESSAGE.parse("PANZERN_PROGRESS", player, panzern.blocksLeft()));
+ for (int i = 0; i < 1000; i++) {
+ if (!panzern.hasNext()) {
+ BauSystem.MESSAGE.send("PANZERN_DONE", player);
+ cancel();
+ return;
+ }
+ panzern.next();
+ }
+ }
+ }.runTaskTimer(BauSystem.getInstance(), 1, 1);
+ }
+
+ private Pair getSelection(Player player) {
+ RegionSelector regionSelector = WorldEdit.getInstance()
+ .getSessionManager()
+ .get(BukkitAdapter.adapt(player))
+ .getRegionSelector(BukkitAdapter.adapt(player.getWorld()));
+
+ try {
+ BlockVector3 min = regionSelector.getRegion().getMinimumPoint();
+ BlockVector3 max = regionSelector.getRegion().getMaximumPoint();
+ return new Pair<>(adapt(player.getWorld(), min), adapt(player.getWorld(), max));
+ } catch (IncompleteRegionException e) {
+ return null;
+ }
+ }
+
+ private Location adapt(World world, BlockVector3 blockVector3) {
+ return new Location(world, blockVector3.getBlockX(), blockVector3.getBlockY(), blockVector3.getBlockZ());
+ }
+}