diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/cuboid/CSchemClipboardFormat.java b/BauSystem_Main/src/de/steamwar/bausystem/features/cuboid/CSchemClipboardFormat.java
new file mode 100644
index 00000000..1fdd8174
--- /dev/null
+++ b/BauSystem_Main/src/de/steamwar/bausystem/features/cuboid/CSchemClipboardFormat.java
@@ -0,0 +1,79 @@
+/*
+ * 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.features.cuboid;
+
+import com.fastasyncworldedit.core.internal.io.parallelgzip.ParallelGZIPOutputStream;
+import com.sk89q.jnbt.NBTOutputStream;
+import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormat;
+import com.sk89q.worldedit.extent.clipboard.io.ClipboardReader;
+import com.sk89q.worldedit.extent.clipboard.io.ClipboardWriter;
+import de.steamwar.bausystem.features.cuboid.io.CSchemWriter;
+
+import java.io.*;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.zip.GZIPOutputStream;
+
+public class CSchemClipboardFormat implements ClipboardFormat {
+
+ @Override
+ public String getName() {
+ return "CSchem";
+ }
+
+ @Override
+ public Set getAliases() {
+ return new HashSet<>(Arrays.asList("cschem"));
+ }
+
+ @Override
+ public ClipboardReader getReader(InputStream inputStream) throws IOException {
+ return null;
+ }
+
+ @Override
+ public ClipboardWriter getWriter(OutputStream outputStream) throws IOException {
+ OutputStream gzip;
+ if (!(outputStream instanceof ParallelGZIPOutputStream) && !(outputStream instanceof GZIPOutputStream)) {
+ OutputStream outputStreamx = new BufferedOutputStream(outputStream);
+ gzip = new GZIPOutputStream(outputStreamx);
+ } else {
+ gzip = outputStream;
+ }
+
+ return new CSchemWriter(new NBTOutputStream(new BufferedOutputStream(gzip)));
+ }
+
+ @Override
+ public boolean isFormat(File file) {
+ return file.getName().endsWith(".cschem");
+ }
+
+ @Override
+ public String getPrimaryFileExtension() {
+ return "cschem";
+ }
+
+ @Override
+ public Set getFileExtensions() {
+ return new HashSet<>(Arrays.asList("cschem"));
+ }
+}
diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/cuboid/TypedCuboid.java b/BauSystem_Main/src/de/steamwar/bausystem/features/cuboid/Cuboid.java
similarity index 60%
rename from BauSystem_Main/src/de/steamwar/bausystem/features/cuboid/TypedCuboid.java
rename to BauSystem_Main/src/de/steamwar/bausystem/features/cuboid/Cuboid.java
index f312ceaa..b3519893 100644
--- a/BauSystem_Main/src/de/steamwar/bausystem/features/cuboid/TypedCuboid.java
+++ b/BauSystem_Main/src/de/steamwar/bausystem/features/cuboid/Cuboid.java
@@ -19,33 +19,45 @@
package de.steamwar.bausystem.features.cuboid;
+import com.sk89q.worldedit.math.BlockVector3;
+import com.sk89q.worldedit.world.block.BlockState;
import lombok.ToString;
@ToString
-public class TypedCuboid {
+public class Cuboid {
+ int x;
+ int y;
+ int z;
+ int dx;
+ int dy;
+ int dz;
+ private BlockState block;
- public int x;
- public int y;
- public int z;
- public int dx;
- public int dy;
- public int dz;
-
- public String blockData;
-
- public TypedCuboid(int x, int y, int z, String blockData) {
- this.x = x;
- this.y = y;
- this.z = z;
+ public Cuboid(BlockVector3 origin, BlockState block) {
+ this.x = origin.getBlockX();
+ this.y = origin.getBlockY();
+ this.z = origin.getBlockZ();
this.dx = 1;
this.dy = 1;
this.dz = 1;
- this.blockData = blockData;
+ this.block = block;
}
public long size() {
return (long) dx * (long) dy * (long) dz;
}
+
+ public BlockVector3 getOrigin() {
+ return BlockVector3.at(x, y, z);
+ }
+
+ public BlockVector3 getSize() {
+ return BlockVector3.at(dx, dy, dz);
+ }
+
+ public BlockState getBlock() {
+ return block;
+ }
}
diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/cuboid/Cuboid2Command.java b/BauSystem_Main/src/de/steamwar/bausystem/features/cuboid/Cuboid2Command.java
deleted file mode 100644
index 68464b3f..00000000
--- a/BauSystem_Main/src/de/steamwar/bausystem/features/cuboid/Cuboid2Command.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * 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.features.cuboid;
-
-import de.steamwar.bausystem.shared.Pair;
-import de.steamwar.bausystem.utils.WorldEditUtils;
-import de.steamwar.command.SWCommand;
-import de.steamwar.linkage.Linked;
-import org.bukkit.Location;
-import org.bukkit.entity.Player;
-import org.bukkit.util.Vector;
-
-import java.io.IOException;
-import java.io.OutputStream;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.zip.GZIPOutputStream;
-
-@Linked
-public class Cuboid2Command extends SWCommand {
-
- public Cuboid2Command() {
- super("cuboid");
- }
-
- @Register
- public void command(Player player) {
- Pair selection = WorldEditUtils.getSelection(player);
- if (selection == null) {
- player.sendMessage("§cDu musst erst eine Auswahl treffen!");
- return;
- }
- Location min = selection.getKey();
- Location max = selection.getValue();
-
- Vector minVec = new Vector(Math.min(min.getX(), max.getX()), Math.min(min.getY(), max.getY()), Math.min(min.getZ(), max.getZ()));
- Vector maxVec = new Vector(Math.max(min.getX(), max.getX()), Math.max(min.getY(), max.getY()), Math.max(min.getZ(), max.getZ()));
-
- CuboidSchematicWriter cuboidSchematicWriter = new CuboidSchematicWriter(minVec, maxVec);
- cuboidSchematicWriter.create(player, cuboidSchematic -> {
- AtomicInteger counter = new AtomicInteger();
- try {
- cuboidSchematic.write(new GZIPOutputStream(new OutputStream() {
- @Override
- public void write(int b) throws IOException {
- counter.incrementAndGet();
- }
- }));
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- player.sendMessage("§aDie Schematic ist " + counter.get() + " Bytes groß!");
- System.out.println(cuboidSchematic);
- });
- }
-}
diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/cuboid/CuboidClipboard.java b/BauSystem_Main/src/de/steamwar/bausystem/features/cuboid/CuboidClipboard.java
new file mode 100644
index 00000000..b23a083d
--- /dev/null
+++ b/BauSystem_Main/src/de/steamwar/bausystem/features/cuboid/CuboidClipboard.java
@@ -0,0 +1,86 @@
+/*
+ * 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.features.cuboid;
+
+import com.sk89q.jnbt.CompoundTag;
+import com.sk89q.worldedit.WorldEditException;
+import com.sk89q.worldedit.entity.Entity;
+import com.sk89q.worldedit.extent.clipboard.Clipboard;
+import com.sk89q.worldedit.math.BlockVector3;
+import com.sk89q.worldedit.regions.Region;
+import com.sk89q.worldedit.world.block.BlockState;
+import lombok.Getter;
+
+import java.util.List;
+import java.util.Map;
+
+@Getter
+public class CuboidClipboard implements Clipboard {
+
+ private Clipboard parent;
+ private List cuboids;
+ private Map order;
+
+ public CuboidClipboard(Clipboard parent, List cuboids, Map order) {
+ this.parent = parent;
+ this.cuboids = cuboids;
+ this.order = order;
+ }
+
+ @Override
+ public Region getRegion() {
+ return parent.getRegion();
+ }
+
+ @Override
+ public BlockVector3 getDimensions() {
+ return parent.getDimensions();
+ }
+
+ @Override
+ public BlockVector3 getOrigin() {
+ return parent.getOrigin();
+ }
+
+ @Override
+ public void setOrigin(BlockVector3 origin) {
+ parent.setOrigin(origin);
+ }
+
+ @Override
+ public void removeEntity(Entity entity) {
+ parent.removeEntity(entity);
+ }
+
+ @Override
+ public BlockVector3 getMinimumPoint() {
+ return parent.getMinimumPoint();
+ }
+
+ @Override
+ public BlockVector3 getMaximumPoint() {
+ return parent.getMaximumPoint();
+ }
+
+ @Override
+ public boolean setTile(int x, int y, int z, CompoundTag tile) throws WorldEditException {
+ return false;
+ }
+}
diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/cuboid/CuboidCommand.java b/BauSystem_Main/src/de/steamwar/bausystem/features/cuboid/CuboidCommand.java
index 6f33f813..8b170b1d 100644
--- a/BauSystem_Main/src/de/steamwar/bausystem/features/cuboid/CuboidCommand.java
+++ b/BauSystem_Main/src/de/steamwar/bausystem/features/cuboid/CuboidCommand.java
@@ -19,182 +19,77 @@
package de.steamwar.bausystem.features.cuboid;
+import com.sk89q.worldedit.extent.clipboard.Clipboard;
+import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormats;
import de.steamwar.bausystem.BauSystem;
-import de.steamwar.bausystem.shared.Pair;
import de.steamwar.bausystem.utils.WorldEditUtils;
import de.steamwar.command.SWCommand;
-import lombok.ToString;
-import org.bukkit.Axis;
-import org.bukkit.Location;
-import org.bukkit.Material;
+import de.steamwar.linkage.Linked;
+import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitRunnable;
-import org.bukkit.util.Vector;
-import java.util.*;
-import java.util.function.Supplier;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.function.Consumer;
-// @Linked
+@Linked
public class CuboidCommand extends SWCommand {
+ static {
+ ClipboardFormats.registerClipboardFormat(new CSchemClipboardFormat());
+ }
+
public CuboidCommand() {
super("cuboid");
}
@Register
- public void genericCommand(Player player) {
- Pair selection = WorldEditUtils.getSelection(player);
- if (selection == null) {
- player.sendMessage("§cDu musst erst eine Auswahl treffen!");
+ public void onCommand(Player player) {
+ Clipboard clipboard = WorldEditUtils.getClipboard(player);
+ if (clipboard == null) {
+ player.sendMessage("§cDu hast keine Schematic geladen!");
return;
}
- Location min = selection.getKey();
- Location max = selection.getValue();
-
- Vector minVec = new Vector(Math.min(min.getX(), max.getX()), Math.min(min.getY(), max.getY()), Math.min(min.getZ(), max.getZ()));
- Vector maxVec = new Vector(Math.max(min.getX(), max.getX()), Math.max(min.getY(), max.getY()), Math.max(min.getZ(), max.getZ()));
-
- Map blocks = new HashMap<>();
- for (int x = min.getBlockX(); x <= max.getBlockX(); x++) {
- for (int y = min.getBlockY(); y <= max.getBlockY(); y++) {
- for (int z = min.getBlockZ(); z <= max.getBlockZ(); z++) {
- blocks.put(new Vector(x, y, z), player.getWorld().getBlockAt(x, y, z).getType());
- }
- }
- }
-
- List left = new ArrayList<>();
- left.add(minVec);
long time = System.currentTimeMillis();
- List cuboids = new ArrayList<>();
- runTickEfficient(left::isEmpty, () -> {
- System.out.println(left.size());
- Vector current = left.remove(0);
- if (current.getX() > maxVec.getX() || current.getY() > maxVec.getY() || current.getZ() > maxVec.getZ()) {
- return;
+ CuboidCreator4 cuboidCreator4 = new CuboidCreator4(clipboard);
+ runAsync(cuboidCreator4, cuboids -> {
+ long t2 = System.currentTimeMillis() - time;
+ player.sendMessage("§aEs wurden " + cuboids.size() + " Cuboids erstellt!");
+ player.sendMessage("§aDas hat " + t2 + "ms gedauert!");
+ player.sendMessage("§aDas sind " + (cuboids.size() / (double) Math.max(t2, 1)) + " Cuboids/ms!");
+
+ CuboidClipboard cuboidClipboard = new CuboidClipboard(clipboard, cuboids, cuboidCreator4.applyOrder());
+ AtomicLong size = new AtomicLong();
+ try {
+ cuboidClipboard.save(new OutputStream() {
+ @Override
+ public void write(int b) throws IOException {
+ size.incrementAndGet();
+ }
+ }, ClipboardFormats.findByAlias("cschem"));
+ } catch (IOException e) {
}
-
- BlockCuboid cuboid = new BlockCuboid(current, blocks.get(current));
- expand(cuboid, maxVec, blocks);
- cuboids.add(cuboid);
-
- left.add(new Vector(cuboid.min.getX(), cuboid.min.getY(), cuboid.max.getZ() + 1));
- left.add(new Vector(cuboid.min.getX(), cuboid.max.getY() + 1, cuboid.min.getZ()));
- left.add(new Vector(cuboid.max.getX() + 1, cuboid.min.getY(), cuboid.min.getZ()));
- }, () -> {
- System.out.println((System.currentTimeMillis() - time) + " ms " + cuboids);
+ player.sendMessage("§aDie Größe der Schematic beträgt " + size.get() + " Bytes!");
});
}
- private void runTickEfficient(Supplier finished, Runnable next, Runnable finishedCallback) {
+ private void runAsync(Iterator iterator, Consumer> result) {
new BukkitRunnable() {
+ private final List list = new ArrayList<>();
+
@Override
public void run() {
- if (finished.get()) {
- cancel();
- finishedCallback.run();
- return;
- }
- long time = System.currentTimeMillis();
- while (System.currentTimeMillis() - time < 50) {
- if (finished.get()) {
- cancel();
- finishedCallback.run();
- return;
- }
- next.run();
- }
+ iterator.forEachRemaining(list::add);
+ Bukkit.getScheduler().runTaskLater(BauSystem.getInstance(), () -> {
+ result.accept(list);
+ }, 1);
}
- }.runTaskTimer(BauSystem.getInstance(), 0, 1);
- }
-
- @ToString
- private static class BlockCuboid {
- private final Vector min;
- private final Vector max;
- private final Material material;
-
- public BlockCuboid(Vector min, Material material) {
- this.min = min.clone();
- this.max = min.clone();
- this.material = material;
- }
- }
-
- private void expand(BlockCuboid cuboid, Vector max, Map blocks) {
- List axes = new ArrayList<>();
- axes.add(Axis.X);
- axes.add(Axis.Y);
- axes.add(Axis.Z);
- do {
- Vector sizes = cuboid.max.clone().subtract(cuboid.min).add(new Vector(1, 1, 1));
- axes.sort(Comparator.comparing(axis -> {
- switch (axis) {
- case X:
- return sizes.getX();
- case Y:
- return sizes.getY();
- case Z:
- return sizes.getZ();
- default:
- return 0.0;
- }
- }));
- axes.removeIf(axis -> {
- Vector direction = new Vector();
- switch (axis) {
- case X:
- direction.setX(1);
- break;
- case Y:
- direction.setY(1);
- break;
- case Z:
- direction.setZ(1);
- break;
- }
- return !expand(cuboid, max, direction, blocks);
- });
- } while (!axes.isEmpty());
- }
-
- private boolean expand(BlockCuboid cuboid, Vector max, Vector direction, Map blocks) {
- if (direction.getX() == 1) {
- if (cuboid.max.getX() + 1 > max.getX()) {
- return false;
- }
- for (double y = cuboid.min.getY(); y <= cuboid.max.getY(); y++) {
- for (double z = cuboid.min.getZ(); z <= cuboid.max.getZ(); z++) {
- if (blocks.get(new Vector(cuboid.max.getX() + 1, y, z)) != cuboid.material) {
- return false;
- }
- }
- }
- } else if (direction.getY() == 1) {
- if (cuboid.max.getY() + 1 > max.getY()) {
- return false;
- }
- for (double x = cuboid.min.getX(); x <= cuboid.max.getX(); x++) {
- for (double z = cuboid.min.getZ(); z <= cuboid.max.getZ(); z++) {
- if (blocks.get(new Vector(x, cuboid.max.getY() + 1, z)) != cuboid.material) {
- return false;
- }
- }
- }
- } else if (direction.getZ() == 1) {
- if (cuboid.max.getZ() + 1 > max.getZ()) {
- return false;
- }
- for (double x = cuboid.min.getX(); x <= cuboid.max.getX(); x++) {
- for (double y = cuboid.min.getY(); y <= cuboid.max.getY(); y++) {
- if (blocks.get(new Vector(x, y, cuboid.max.getZ() + 1)) != cuboid.material) {
- return false;
- }
- }
- }
- }
- cuboid.max.add(direction);
- return true;
+ }.runTaskAsynchronously(BauSystem.getInstance());
}
}
diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/cuboid/clipboard/CuboidCreator.java b/BauSystem_Main/src/de/steamwar/bausystem/features/cuboid/CuboidCreator.java
similarity index 80%
rename from BauSystem_Main/src/de/steamwar/bausystem/features/cuboid/clipboard/CuboidCreator.java
rename to BauSystem_Main/src/de/steamwar/bausystem/features/cuboid/CuboidCreator.java
index 80763148..320ec368 100644
--- a/BauSystem_Main/src/de/steamwar/bausystem/features/cuboid/clipboard/CuboidCreator.java
+++ b/BauSystem_Main/src/de/steamwar/bausystem/features/cuboid/CuboidCreator.java
@@ -17,18 +17,17 @@
* along with this program. If not, see .
*/
-package de.steamwar.bausystem.features.cuboid.clipboard;
+package de.steamwar.bausystem.features.cuboid;
import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.world.block.BlockState;
-import lombok.ToString;
import org.bukkit.Axis;
import org.bukkit.util.Vector;
import java.util.*;
-public class CuboidCreator implements Iterator {
+public class CuboidCreator implements Iterator {
private static final List AXES = Arrays.asList(
new Axis[]{Axis.X, Axis.Y, Axis.Z},
@@ -86,9 +85,9 @@ public class CuboidCreator implements Iterator {
}
}
- left.add(BlockVector3.at(origin.getBlockX() + cuboid.dx + 1, origin.getBlockY(), origin.getBlockZ()));
- left.add(BlockVector3.at(origin.getBlockX(), origin.getBlockY() + cuboid.dy + 1, origin.getBlockZ()));
- left.add(BlockVector3.at(origin.getBlockX(), origin.getBlockY(), origin.getBlockZ() + cuboid.dz + 1));
+ left.add(BlockVector3.at(origin.getBlockX() + cuboid.dx, origin.getBlockY(), origin.getBlockZ()));
+ left.add(BlockVector3.at(origin.getBlockX(), origin.getBlockY() + cuboid.dy, origin.getBlockZ()));
+ left.add(BlockVector3.at(origin.getBlockX(), origin.getBlockY(), origin.getBlockZ() + cuboid.dz));
return cuboid;
}
@@ -117,7 +116,7 @@ public class CuboidCreator implements Iterator {
if (direction.getX() == 1) {
for (int y = cuboid.y; y < cuboid.y + cuboid.dy; y++) {
for (int z = cuboid.z; z < cuboid.z + cuboid.dz; z++) {
- if (!blocks.contains(BlockVector3.at(cuboid.x + cuboid.dx + 1, y, z))) {
+ if (!blocks.contains(BlockVector3.at(cuboid.x + cuboid.dx, y, z))) {
return false;
}
}
@@ -125,7 +124,7 @@ public class CuboidCreator implements Iterator {
} else if (direction.getY() == 1) {
for (int x = cuboid.x; x < cuboid.x + cuboid.dx; x++) {
for (int z = cuboid.z; z < cuboid.z + cuboid.dz; z++) {
- if (!blocks.contains(BlockVector3.at(x, cuboid.y + cuboid.dy + 1, z))) {
+ if (!blocks.contains(BlockVector3.at(x, cuboid.y + cuboid.dy, z))) {
return false;
}
}
@@ -133,7 +132,7 @@ public class CuboidCreator implements Iterator {
} else if (direction.getZ() == 1) {
for (int x = cuboid.x; x < cuboid.x + cuboid.dx; x++) {
for (int y = cuboid.y; y < cuboid.y + cuboid.dy; y++) {
- if (!blocks.contains(BlockVector3.at(x, y, cuboid.z + cuboid.dz + 1))) {
+ if (!blocks.contains(BlockVector3.at(x, y, cuboid.z + cuboid.dz))) {
return false;
}
}
@@ -148,43 +147,4 @@ public class CuboidCreator implements Iterator {
}
return true;
}
-
- @ToString
- public static class Cuboid {
- int x;
- int y;
- int z;
- int dx;
- int dy;
- int dz;
- private BlockState block;
-
- public Cuboid(BlockVector3 origin, BlockState block) {
- this.x = origin.getBlockX();
- this.y = origin.getBlockY();
- this.z = origin.getBlockZ();
-
- this.dx = 1;
- this.dy = 1;
- this.dz = 1;
-
- this.block = block;
- }
-
- public long size() {
- return (long) dx * (long) dy * (long) dz;
- }
-
- public BlockVector3 getOrigin() {
- return BlockVector3.at(x, y, z);
- }
-
- public BlockVector3 getSize() {
- return BlockVector3.at(dx, dy, dz);
- }
-
- public BlockState getBlock() {
- return block;
- }
- }
}
diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/cuboid/CuboidCreator2.java b/BauSystem_Main/src/de/steamwar/bausystem/features/cuboid/CuboidCreator2.java
new file mode 100644
index 00000000..a2b5abe4
--- /dev/null
+++ b/BauSystem_Main/src/de/steamwar/bausystem/features/cuboid/CuboidCreator2.java
@@ -0,0 +1,147 @@
+/*
+ * 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.features.cuboid;
+
+import com.sk89q.worldedit.extent.clipboard.Clipboard;
+import com.sk89q.worldedit.math.BlockVector3;
+import com.sk89q.worldedit.world.block.BlockState;
+import org.bukkit.Axis;
+import org.bukkit.util.Vector;
+
+import java.util.*;
+
+public class CuboidCreator2 implements Iterator {
+
+ private static final List AXES = Arrays.asList(
+ new Axis[]{Axis.X, Axis.Y, Axis.Z},
+ new Axis[]{Axis.X, Axis.Z, Axis.Y},
+ new Axis[]{Axis.Y, Axis.X, Axis.Z},
+ new Axis[]{Axis.Y, Axis.Z, Axis.X},
+ new Axis[]{Axis.Z, Axis.X, Axis.Y},
+ new Axis[]{Axis.Z, Axis.Y, Axis.X}
+ );
+
+ private Map> reverseBlocks = new HashMap<>();
+
+ public CuboidCreator2(Clipboard clipboard) {
+ clipboard.getRegion().forEach(blockVector3 -> {
+ BlockVector3 position = blockVector3.subtract(clipboard.getMinimumPoint());
+ BlockState block = clipboard.getBlock(blockVector3);
+ reverseBlocks.computeIfAbsent(block, k -> new HashSet<>()).add(position);
+ });
+ }
+
+ @Override
+ public boolean hasNext() {
+ return !reverseBlocks.isEmpty();
+ }
+
+ @Override
+ public Cuboid next() {
+ Cuboid cuboid = null;
+ BlockState toRemove = null;
+ for (Map.Entry> entry : reverseBlocks.entrySet()) {
+ BlockState block = entry.getKey();
+ Set positions = entry.getValue();
+
+ for (BlockVector3 position : positions) {
+ for (Axis[] axes : AXES) {
+ Cuboid currentCuboid = new Cuboid(position, block);
+ expand(currentCuboid, new ArrayList<>(Arrays.asList(axes)), entry.getValue());
+ if (cuboid == null || cuboid.size() < currentCuboid.size()) {
+ cuboid = currentCuboid;
+ }
+ }
+ }
+
+ for (int x = cuboid.x; x < cuboid.x + cuboid.dx; x++) {
+ for (int y = cuboid.y; y < cuboid.y + cuboid.dy; y++) {
+ for (int z = cuboid.z; z < cuboid.z + cuboid.dz; z++) {
+ positions.remove(BlockVector3.at(x, y, z));
+ }
+ }
+ }
+ if (positions.isEmpty()) {
+ toRemove = block;
+ }
+ break;
+ }
+ if (toRemove != null) {
+ reverseBlocks.remove(toRemove);
+ }
+ return cuboid;
+ }
+
+ private void expand(Cuboid cuboid, List axes, Set blocks) {
+ while (!axes.isEmpty()) {
+ axes.removeIf(axis -> {
+ org.bukkit.util.Vector direction = new org.bukkit.util.Vector();
+ switch (axis) {
+ case X:
+ direction.setX(1);
+ break;
+ case Y:
+ direction.setY(1);
+ break;
+ case Z:
+ direction.setZ(1);
+ break;
+ }
+ return !expand(cuboid, direction, blocks);
+ });
+ }
+ }
+
+ private boolean expand(Cuboid cuboid, Vector direction, Set blocks) {
+ if (direction.getX() == 1) {
+ for (int y = cuboid.y; y < cuboid.y + cuboid.dy; y++) {
+ for (int z = cuboid.z; z < cuboid.z + cuboid.dz; z++) {
+ if (!blocks.contains(BlockVector3.at(cuboid.x + cuboid.dx, y, z))) {
+ return false;
+ }
+ }
+ }
+ } else if (direction.getY() == 1) {
+ for (int x = cuboid.x; x < cuboid.x + cuboid.dx; x++) {
+ for (int z = cuboid.z; z < cuboid.z + cuboid.dz; z++) {
+ if (!blocks.contains(BlockVector3.at(x, cuboid.y + cuboid.dy, z))) {
+ return false;
+ }
+ }
+ }
+ } else if (direction.getZ() == 1) {
+ for (int x = cuboid.x; x < cuboid.x + cuboid.dx; x++) {
+ for (int y = cuboid.y; y < cuboid.y + cuboid.dy; y++) {
+ if (!blocks.contains(BlockVector3.at(x, y, cuboid.z + cuboid.dz))) {
+ return false;
+ }
+ }
+ }
+ }
+ if (direction.getX() == 1) {
+ cuboid.dx++;
+ } else if (direction.getY() == 1) {
+ cuboid.dy++;
+ } else if (direction.getZ() == 1) {
+ cuboid.dz++;
+ }
+ return true;
+ }
+}
diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/cuboid/CuboidCreator3.java b/BauSystem_Main/src/de/steamwar/bausystem/features/cuboid/CuboidCreator3.java
new file mode 100644
index 00000000..daf8c955
--- /dev/null
+++ b/BauSystem_Main/src/de/steamwar/bausystem/features/cuboid/CuboidCreator3.java
@@ -0,0 +1,169 @@
+/*
+ * 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.features.cuboid;
+
+import com.sk89q.worldedit.extent.clipboard.Clipboard;
+import com.sk89q.worldedit.math.BlockVector3;
+import com.sk89q.worldedit.world.block.BlockState;
+import com.sk89q.worldedit.world.block.BlockTypes;
+import org.bukkit.Axis;
+import org.bukkit.Material;
+import org.bukkit.util.Vector;
+
+import java.util.*;
+
+public class CuboidCreator3 implements Iterator {
+
+ private static final List AXES = Arrays.asList(
+ new Axis[]{Axis.X, Axis.Y, Axis.Z},
+ new Axis[]{Axis.X, Axis.Z, Axis.Y},
+ new Axis[]{Axis.Y, Axis.X, Axis.Z},
+ new Axis[]{Axis.Y, Axis.Z, Axis.X},
+ new Axis[]{Axis.Z, Axis.X, Axis.Y},
+ new Axis[]{Axis.Z, Axis.Y, Axis.X}
+ );
+
+ private static final Set invisible = new HashSet<>();
+ static {
+ for (Material value : Material.values()) {
+ if (!value.isOccluding() || value.isAir()) {
+ invisible.add("minecraft:" + value.name().toLowerCase());
+ }
+ }
+ }
+
+ private Set invisibleBlocks = new HashSet<>();
+ private Map> reverseBlocks = new HashMap<>();
+
+ public CuboidCreator3(Clipboard clipboard) {
+ clipboard.getRegion().forEach(blockVector3 -> {
+ BlockVector3 position = blockVector3.subtract(clipboard.getMinimumPoint());
+ BlockState block = clipboard.getBlock(blockVector3);
+ if (block.getAsString().startsWith("minecraft:redstone_wire") && !block.getAsString().equals("minecraft:redstone_wire[east=none,north=none,power=0,south=none,west=none]")) {
+ block = BlockState.get("minecraft:redstone_wire[east=side,north=side,power=0,south=side,west=side]");
+ }
+ reverseBlocks.computeIfAbsent(block, k -> new HashSet<>()).add(position);
+ if (invisible.contains(block.getBlockType().getId())) {
+ invisibleBlocks.add(position);
+ }
+ });
+ }
+
+ @Override
+ public boolean hasNext() {
+ return !reverseBlocks.isEmpty();
+ }
+
+ @Override
+ public Cuboid next() {
+ Cuboid cuboid = null;
+ BlockState toRemove = null;
+ for (Map.Entry> entry : reverseBlocks.entrySet()) {
+ BlockState block = entry.getKey();
+ Set positions = entry.getValue();
+
+ for (BlockVector3 position : positions) {
+ for (Axis[] axes : AXES) {
+ Cuboid currentCuboid = new Cuboid(position, block);
+ expand(currentCuboid, new ArrayList<>(Arrays.asList(axes)), entry.getValue());
+ if (cuboid == null || cuboid.size() < currentCuboid.size()) {
+ cuboid = currentCuboid;
+ }
+ }
+ }
+
+ for (int x = cuboid.x; x < cuboid.x + cuboid.dx; x++) {
+ for (int y = cuboid.y; y < cuboid.y + cuboid.dy; y++) {
+ for (int z = cuboid.z; z < cuboid.z + cuboid.dz; z++) {
+ positions.remove(BlockVector3.at(x, y, z));
+ }
+ }
+ }
+ if (positions.isEmpty()) {
+ toRemove = block;
+ }
+ break;
+ }
+ if (toRemove != null) {
+ reverseBlocks.remove(toRemove);
+ }
+ return cuboid;
+ }
+
+ private void expand(Cuboid cuboid, List axes, Set blocks) {
+ while (!axes.isEmpty()) {
+ axes.removeIf(axis -> {
+ Vector direction = new Vector();
+ switch (axis) {
+ case X:
+ direction.setX(1);
+ break;
+ case Y:
+ direction.setY(1);
+ break;
+ case Z:
+ direction.setZ(1);
+ break;
+ }
+ return !expand(cuboid, direction, blocks);
+ });
+ }
+ }
+
+ private boolean expand(Cuboid cuboid, Vector direction, Set blocks) {
+ boolean selfInvisible = invisibleBlocks.contains(BlockVector3.at(cuboid.x, cuboid.y, cuboid.z));
+ if (direction.getX() == 1) {
+ for (int y = cuboid.y; y < cuboid.y + cuboid.dy; y++) {
+ for (int z = cuboid.z; z < cuboid.z + cuboid.dz; z++) {
+ BlockVector3 pos = BlockVector3.at(cuboid.x + cuboid.dx, y, z);
+ if (!blocks.contains(pos) && (!invisibleBlocks.contains(pos) || selfInvisible)) {
+ return false;
+ }
+ }
+ }
+ } else if (direction.getY() == 1) {
+ for (int x = cuboid.x; x < cuboid.x + cuboid.dx; x++) {
+ for (int z = cuboid.z; z < cuboid.z + cuboid.dz; z++) {
+ BlockVector3 pos = BlockVector3.at(x, cuboid.y + cuboid.dy, z);
+ if (!blocks.contains(pos) && (!invisibleBlocks.contains(pos) || selfInvisible)) {
+ return false;
+ }
+ }
+ }
+ } else if (direction.getZ() == 1) {
+ for (int x = cuboid.x; x < cuboid.x + cuboid.dx; x++) {
+ for (int y = cuboid.y; y < cuboid.y + cuboid.dy; y++) {
+ BlockVector3 pos = BlockVector3.at(x, y, cuboid.z + cuboid.dz);
+ if (!blocks.contains(pos) && (!invisibleBlocks.contains(pos) || selfInvisible)) {
+ return false;
+ }
+ }
+ }
+ }
+ if (direction.getX() == 1) {
+ cuboid.dx++;
+ } else if (direction.getY() == 1) {
+ cuboid.dy++;
+ } else if (direction.getZ() == 1) {
+ cuboid.dz++;
+ }
+ return true;
+ }
+}
diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/cuboid/CuboidCreator4.java b/BauSystem_Main/src/de/steamwar/bausystem/features/cuboid/CuboidCreator4.java
new file mode 100644
index 00000000..1be0b2d8
--- /dev/null
+++ b/BauSystem_Main/src/de/steamwar/bausystem/features/cuboid/CuboidCreator4.java
@@ -0,0 +1,181 @@
+/*
+ * 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.features.cuboid;
+
+import com.sk89q.worldedit.extent.clipboard.Clipboard;
+import com.sk89q.worldedit.math.BlockVector3;
+import com.sk89q.worldedit.world.block.BlockState;
+import org.bukkit.Axis;
+import org.bukkit.util.Vector;
+
+import java.util.*;
+
+public class CuboidCreator4 implements Iterator {
+
+ private static final List AXES = Arrays.asList(
+ new Axis[]{Axis.X, Axis.Y, Axis.Z},
+ new Axis[]{Axis.X, Axis.Z, Axis.Y},
+ new Axis[]{Axis.Y, Axis.X, Axis.Z},
+ new Axis[]{Axis.Y, Axis.Z, Axis.X},
+ new Axis[]{Axis.Z, Axis.X, Axis.Y},
+ new Axis[]{Axis.Z, Axis.Y, Axis.X}
+ );
+
+ private List invisibleOrder = new ArrayList<>();
+ private Map> invisible = new HashMap<>();
+
+ private Map blocks = new HashMap<>();
+ private Map> reverseBlocks = new HashMap<>();
+
+ public CuboidCreator4(Clipboard clipboard) {
+ clipboard.getRegion().forEach(blockVector3 -> {
+ BlockVector3 position = blockVector3.subtract(clipboard.getMinimumPoint());
+ BlockState block = clipboard.getBlock(blockVector3);
+ blocks.put(position, block);
+ reverseBlocks.computeIfAbsent(block, k -> new HashSet<>()).add(position);
+ });
+ invisibleOrder.addAll(reverseBlocks.keySet());
+ invisibleOrder.sort(Comparator.comparingInt(o -> -reverseBlocks.get(o).size()));
+ invisibleOrder.remove(BlockState.get("minecraft:air"));
+ invisibleOrder.add(BlockState.get("minecraft:air"));
+ for (int i = 0; i < invisibleOrder.size(); i++) {
+ BlockState block = invisibleOrder.get(i);
+ for (int j = i + 1; j < invisibleOrder.size(); j++) {
+ invisible.computeIfAbsent(block, k -> new HashSet<>()).add(invisibleOrder.get(j));
+ }
+ }
+ }
+
+ public Map applyOrder() {
+ Map order = new HashMap<>();
+ for (int i = 0; i < invisibleOrder.size(); i++) {
+ order.put(invisibleOrder.get(i), i);
+ }
+ return order;
+ }
+
+ @Override
+ public boolean hasNext() {
+ return !reverseBlocks.isEmpty();
+ }
+
+ @Override
+ public Cuboid next() {
+ Cuboid cuboid = null;
+ BlockState toRemove = null;
+ for (Map.Entry> entry : reverseBlocks.entrySet()) {
+ BlockState block = entry.getKey();
+ List positions = new ArrayList<>(entry.getValue());
+
+ for (int i = 0; i < positions.size(); i++) {
+ BlockVector3 position = positions.get(i);
+ for (Axis[] axes : AXES) {
+ Cuboid currentCuboid = new Cuboid(position, block);
+ expand(currentCuboid, new ArrayList<>(Arrays.asList(axes)), entry.getValue());
+ if (cuboid == null || cuboid.size() < currentCuboid.size()) {
+ cuboid = currentCuboid;
+ if (cuboid.size() > positions.size()) {
+ break;
+ }
+ }
+ }
+ if (cuboid.size() > positions.size()) {
+ break;
+ }
+ }
+
+ for (int x = cuboid.x; x < cuboid.x + cuboid.dx; x++) {
+ for (int y = cuboid.y; y < cuboid.y + cuboid.dy; y++) {
+ for (int z = cuboid.z; z < cuboid.z + cuboid.dz; z++) {
+ entry.getValue().remove(BlockVector3.at(x, y, z));
+ }
+ }
+ }
+ if (entry.getValue().isEmpty()) {
+ toRemove = block;
+ }
+ break;
+ }
+ if (toRemove != null) {
+ reverseBlocks.remove(toRemove);
+ }
+ return cuboid;
+ }
+
+ private void expand(Cuboid cuboid, List axes, Set blocks) {
+ while (!axes.isEmpty()) {
+ axes.removeIf(axis -> {
+ Vector direction = new Vector();
+ switch (axis) {
+ case X:
+ direction.setX(1);
+ break;
+ case Y:
+ direction.setY(1);
+ break;
+ case Z:
+ direction.setZ(1);
+ break;
+ }
+ return !expand(cuboid, direction, blocks);
+ });
+ }
+ }
+
+ private boolean expand(Cuboid cuboid, Vector direction, Set blocks) {
+ Set invisible = this.invisible.getOrDefault(cuboid.getBlock(), new HashSet<>());
+ if (direction.getX() == 1) {
+ for (int y = cuboid.y; y < cuboid.y + cuboid.dy; y++) {
+ for (int z = cuboid.z; z < cuboid.z + cuboid.dz; z++) {
+ BlockVector3 pos = BlockVector3.at(cuboid.x + cuboid.dx, y, z);
+ if (!blocks.contains(pos) && !invisible.contains(this.blocks.get(pos))) {
+ return false;
+ }
+ }
+ }
+ } else if (direction.getY() == 1) {
+ for (int x = cuboid.x; x < cuboid.x + cuboid.dx; x++) {
+ for (int z = cuboid.z; z < cuboid.z + cuboid.dz; z++) {
+ BlockVector3 pos = BlockVector3.at(x, cuboid.y + cuboid.dy, z);
+ if (!blocks.contains(pos) && !invisible.contains(this.blocks.get(pos))) {
+ return false;
+ }
+ }
+ }
+ } else if (direction.getZ() == 1) {
+ for (int x = cuboid.x; x < cuboid.x + cuboid.dx; x++) {
+ for (int y = cuboid.y; y < cuboid.y + cuboid.dy; y++) {
+ BlockVector3 pos = BlockVector3.at(x, y, cuboid.z + cuboid.dz);
+ if (!blocks.contains(pos) && !invisible.contains(this.blocks.get(pos))) {
+ return false;
+ }
+ }
+ }
+ }
+ if (direction.getX() == 1) {
+ cuboid.dx++;
+ } else if (direction.getY() == 1) {
+ cuboid.dy++;
+ } else if (direction.getZ() == 1) {
+ cuboid.dz++;
+ }
+ return true;
+ }
+}
diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/cuboid/CuboidSchematic.java b/BauSystem_Main/src/de/steamwar/bausystem/features/cuboid/CuboidSchematic.java
deleted file mode 100644
index 5505d15a..00000000
--- a/BauSystem_Main/src/de/steamwar/bausystem/features/cuboid/CuboidSchematic.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * 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.features.cuboid;
-
-import com.sk89q.jnbt.*;
-import lombok.Getter;
-
-import java.io.IOException;
-import java.io.OutputStream;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-@Getter
-public class CuboidSchematic {
- private Pos offset;
- private Pos size;
- private Map> cuboids = new HashMap<>();
-
- public CuboidSchematic(Pos offset, Pos size) {
- this.offset = offset;
- this.size = size;
- }
-
- public void addCuboid(TypedCuboid cuboid) {
- cuboids.computeIfAbsent(cuboid.blockData, s -> new ArrayList<>()).add(cuboid);
- }
-
- public void write(OutputStream outputStream) {
- Map schematic = new HashMap<>();
- schematic.put("OffsetX", new IntTag(offset.x));
- schematic.put("OffsetY", new IntTag(offset.y));
- schematic.put("OffsetZ", new IntTag(offset.z));
- schematic.put("SizeX", new IntTag(size.x));
- schematic.put("SizeY", new IntTag(size.y));
- schematic.put("SizeZ", new IntTag(size.z));
-
- Map cuboidMap = new HashMap<>();
- for (Map.Entry> entry : cuboids.entrySet()) {
- byte[] cuboidArray = new byte[entry.getValue().size() * 15];
- for (int i = 0; i < entry.getValue().size(); i++) {
- TypedCuboid cuboid = entry.getValue().get(i);
- List bytes = new ArrayList<>();
- writeVarInt(cuboid.x, bytes);
- writeVarInt(cuboid.y, bytes);
- writeVarInt(cuboid.z, bytes);
- writeVarInt(cuboid.dx, bytes);
- writeVarInt(cuboid.dy, bytes);
- writeVarInt(cuboid.dz, bytes);
- }
- cuboidMap.put(entry.getKey(), new ByteArrayTag(cuboidArray));
- }
- schematic.put("Cuboids", new CompoundTag(cuboidMap));
-
- CompoundTag compoundTag = new CompoundTag(schematic);
- try {
- NBTOutputStream nbtOutputStream = new NBTOutputStream(outputStream);
- nbtOutputStream.writeTag(compoundTag);
- nbtOutputStream.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
-
- private static void writeVarInt(int value, List bytes) {
- while (true) {
- if (value < 128) {
- bytes.add((byte) value);
- return;
- } else {
- bytes.add((byte) (value & 127 | 128));
- value >>>= 7;
- }
- }
- }
-}
diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/cuboid/CuboidSchematicWriter.java b/BauSystem_Main/src/de/steamwar/bausystem/features/cuboid/CuboidSchematicWriter.java
deleted file mode 100644
index 32d89249..00000000
--- a/BauSystem_Main/src/de/steamwar/bausystem/features/cuboid/CuboidSchematicWriter.java
+++ /dev/null
@@ -1,199 +0,0 @@
-/*
- * 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.features.cuboid;
-
-import de.steamwar.bausystem.BauSystem;
-import org.bukkit.Axis;
-import org.bukkit.entity.Player;
-import org.bukkit.scheduler.BukkitRunnable;
-import org.bukkit.util.Consumer;
-import org.bukkit.util.Vector;
-
-import java.util.*;
-import java.util.function.Supplier;
-import java.util.stream.Collectors;
-
-public class CuboidSchematicWriter {
-
- private static final List AXES = Arrays.asList(
- new Axis[]{Axis.X, Axis.Y, Axis.Z},
- new Axis[]{Axis.X, Axis.Z, Axis.Y},
- new Axis[]{Axis.Y, Axis.X, Axis.Z},
- new Axis[]{Axis.Y, Axis.Z, Axis.X},
- new Axis[]{Axis.Z, Axis.X, Axis.Y},
- new Axis[]{Axis.Z, Axis.Y, Axis.X}
- );
-
- private Pos min;
- private Pos max;
-
- public CuboidSchematicWriter(Vector min, Vector max) {
- this.min = new Pos(min);
- this.max = new Pos(max);
- }
-
- public void create(Player player, Consumer consumer) {
- // Setup
- Pos playerPos = new Pos(player.getLocation());
- Pos offset = min.sub(playerPos);
- Map blocks = CuboidSchematicWriter.getBlocks(player, min, max); // Needs to be optimized
- Map> reverseBlocks = reverse(blocks);
-
- // Create CuboidSchematic
- CuboidSchematic schematic = new CuboidSchematic(offset, max.sub(min));
-
- // Create Cuboids
- long time = System.currentTimeMillis();
- List left = new ArrayList<>();
- left.add(new Pos(0, 0, 0));
- runTickEfficient(left::isEmpty, () -> {
- Pos current = left.remove(0);
- String block = blocks.remove(current);
- if (block == null) {
- return;
- }
-
- TypedCuboid cuboid = null;
- for (Axis[] axes : AXES) {
- TypedCuboid currentCuboid = new TypedCuboid(current.x, current.y, current.z, block);
- expand(currentCuboid, new ArrayList<>(Arrays.asList(axes)), reverseBlocks);
- if (cuboid == null || currentCuboid.size() > cuboid.size()) {
- cuboid = currentCuboid;
- }
- }
- Set cuboidBlocks = reverseBlocks.get(block);
- for (int x = cuboid.x; x < cuboid.x + cuboid.dx; x++) {
- for (int y = cuboid.y; y < cuboid.y + cuboid.dy; y++) {
- for (int z = cuboid.z; z < cuboid.z + cuboid.dz; z++) {
- Pos pos = new Pos(x, y, z);
- cuboidBlocks.remove(pos);
- blocks.remove(pos);
- }
- }
- }
- schematic.addCuboid(cuboid);
-
- left.add(new Pos(current.x + cuboid.dx + 1, current.y, current.z));
- left.add(new Pos(current.x, current.y + cuboid.dy + 1, current.z));
- left.add(new Pos(current.x, current.y, current.z + cuboid.dz + 1));
- }, () -> {
- long elapsed = System.currentTimeMillis() - time;
- long cuboids = schematic.getCuboids().values().stream().mapToLong(List::size).sum();
- System.out.println("Finished in " + elapsed + "ms with " + cuboids + " cuboids");
- System.out.println("Average: " + (cuboids / elapsed) + " cuboids per ms");
- System.out.println("Types: " + schematic.getCuboids().entrySet().stream().map(e -> e.getKey() + ": " + e.getValue().size()).collect(Collectors.joining(", ")));
- consumer.accept(schematic);
- });
- }
-
- private void runTickEfficient(Supplier finished, Runnable next, Runnable finishedCallback) {
- new BukkitRunnable() {
- @Override
- public void run() {
- long time = System.currentTimeMillis();
- while (System.currentTimeMillis() - time < 50) {
- if (finished.get()) {
- cancel();
- finishedCallback.run();
- return;
- }
- next.run();
- }
- }
- }.runTaskTimer(BauSystem.getInstance(), 0, 1);
- }
-
- private static Map getBlocks(Player player, Pos min, Pos max) {
- Map blocks = new HashMap<>();
- for (int x = min.x; x <= max.x; x++) {
- for (int y = min.y; y <= max.y; y++) {
- for (int z = min.z; z <= max.z; z++) {
- blocks.put(new Pos(x - min.x, y - min.y, z - min.z), player.getWorld().getBlockAt(x, y, z).getBlockData().getAsString());
- }
- }
- }
- return blocks;
- }
-
- private static Map> reverse(Map input) {
- Map> output = new HashMap<>();
- for (Map.Entry entry : input.entrySet()) {
- output.computeIfAbsent(entry.getValue(), k -> new HashSet<>()).add(entry.getKey());
- }
- return output;
- }
-
- private static void expand(TypedCuboid cuboid, List axes, Map> reverseBlocks) {
- while (!axes.isEmpty()) {
- axes.removeIf(axis -> {
- Vector direction = new Vector();
- switch (axis) {
- case X:
- direction.setX(1);
- break;
- case Y:
- direction.setY(1);
- break;
- case Z:
- direction.setZ(1);
- break;
- }
- return !expand(cuboid, direction, reverseBlocks);
- });
- }
- }
-
- private static boolean expand(TypedCuboid cuboid, Vector direction, Map> reverseBlocks) {
- Set blocks = reverseBlocks.get(cuboid.blockData);
- if (direction.getX() == 1) {
- for (int y = cuboid.y; y < cuboid.y + cuboid.dy; y++) {
- for (int z = cuboid.z; z < cuboid.z + cuboid.dz; z++) {
- if (!blocks.contains(new Pos(cuboid.x + cuboid.dx + 1, y, z))) {
- return false;
- }
- }
- }
- } else if (direction.getY() == 1) {
- for (int x = cuboid.x; x < cuboid.x + cuboid.dx; x++) {
- for (int z = cuboid.z; z < cuboid.z + cuboid.dz; z++) {
- if (!blocks.contains(new Pos(x, cuboid.y + cuboid.dy + 1, z))) {
- return false;
- }
- }
- }
- } else if (direction.getZ() == 1) {
- for (int x = cuboid.x; x < cuboid.x + cuboid.dx; x++) {
- for (int y = cuboid.y; y < cuboid.y + cuboid.dy; y++) {
- if (!blocks.contains(new Pos(x, y, cuboid.z + cuboid.dz + 1))) {
- return false;
- }
- }
- }
- }
- if (direction.getX() == 1) {
- cuboid.dx++;
- } else if (direction.getY() == 1) {
- cuboid.dy++;
- } else if (direction.getZ() == 1) {
- cuboid.dz++;
- }
- return true;
- }
-}
diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/cuboid/Pos.java b/BauSystem_Main/src/de/steamwar/bausystem/features/cuboid/Pos.java
deleted file mode 100644
index e746d750..00000000
--- a/BauSystem_Main/src/de/steamwar/bausystem/features/cuboid/Pos.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * 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.features.cuboid;
-
-import lombok.EqualsAndHashCode;
-import lombok.ToString;
-import org.bukkit.Location;
-import org.bukkit.util.Vector;
-
-@ToString
-@EqualsAndHashCode
-public class Pos {
- public final int x;
- public final int y;
- public final int z;
-
- public Pos(int x, int y, int z) {
- this.x = x;
- this.y = y;
- this.z = z;
- }
-
- public Pos(Location loc) {
- this.x = loc.getBlockX();
- this.y = loc.getBlockY();
- this.z = loc.getBlockZ();
- }
-
- public Pos(Vector vec) {
- this.x = vec.getBlockX();
- this.y = vec.getBlockY();
- this.z = vec.getBlockZ();
- }
-
- public Pos add(int x, int y, int z) {
- return new Pos(this.x + x, this.y + y, this.z + z);
- }
-
- public Pos add(Pos pos) {
- return new Pos(this.x + pos.x, this.y + pos.y, this.z + pos.z);
- }
-
- public Pos sub(int x, int y, int z) {
- return new Pos(this.x - x, this.y - y, this.z - z);
- }
-
- public Pos sub(Pos pos) {
- return new Pos(this.x - pos.x, this.y - pos.y, this.z - pos.z);
- }
-}
diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/cuboid/clipboard/CuboidCommand.java b/BauSystem_Main/src/de/steamwar/bausystem/features/cuboid/clipboard/CuboidCommand.java
deleted file mode 100644
index d0fc8978..00000000
--- a/BauSystem_Main/src/de/steamwar/bausystem/features/cuboid/clipboard/CuboidCommand.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * 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.features.cuboid.clipboard;
-
-import com.sk89q.worldedit.extent.clipboard.Clipboard;
-import de.steamwar.bausystem.utils.WorldEditUtils;
-import de.steamwar.command.SWCommand;
-import de.steamwar.linkage.Linked;
-import org.bukkit.entity.Player;
-
-import java.util.concurrent.atomic.AtomicInteger;
-
-@Linked
-public class CuboidCommand extends SWCommand {
-
- public CuboidCommand() {
- super("clipboardcuboid");
- }
-
- @Register
- public void onCommand(Player player) {
- Clipboard clipboard = WorldEditUtils.getClipboard(player);
- if (clipboard == null) {
- player.sendMessage("§cDu hast keine Schematic geladen!");
- return;
- }
-
- long time = System.currentTimeMillis();
- AtomicInteger counter = new AtomicInteger();
- new CuboidCreator(clipboard).forEachRemaining(cuboid -> {
- counter.incrementAndGet();
- });
- time = System.currentTimeMillis() - time;
- player.sendMessage("§aEs wurden " + counter.get() + " Cuboids erstellt!");
- player.sendMessage("§aDas hat " + time + "ms gedauert!");
- player.sendMessage("§aDas sind " + (counter.get() / Math.max(time, 1)) + " Cuboids/ms!");
- }
-}
diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/cuboid/io/CSchemWriter.java b/BauSystem_Main/src/de/steamwar/bausystem/features/cuboid/io/CSchemWriter.java
new file mode 100644
index 00000000..2d8fb7ca
--- /dev/null
+++ b/BauSystem_Main/src/de/steamwar/bausystem/features/cuboid/io/CSchemWriter.java
@@ -0,0 +1,151 @@
+/*
+ * 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.features.cuboid.io;
+
+import com.sk89q.jnbt.ByteArrayTag;
+import com.sk89q.jnbt.NBTOutputStream;
+import com.sk89q.worldedit.WorldEdit;
+import com.sk89q.worldedit.extension.platform.Capability;
+import com.sk89q.worldedit.extent.clipboard.Clipboard;
+import com.sk89q.worldedit.extent.clipboard.io.ClipboardWriter;
+import com.sk89q.worldedit.math.BlockVector3;
+import com.sk89q.worldedit.regions.Region;
+import com.sk89q.worldedit.world.block.BlockState;
+import de.steamwar.bausystem.features.cuboid.Cuboid;
+import de.steamwar.bausystem.features.cuboid.CuboidClipboard;
+import de.steamwar.bausystem.features.cuboid.CuboidCreator;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class CSchemWriter implements ClipboardWriter {
+
+ private static final int CURRENT_VERSION = 1;
+ private final NBTOutputStream outputStream;
+
+ public CSchemWriter(NBTOutputStream outputStream) {
+ this.outputStream = outputStream;
+ }
+
+ @Override
+ public void write(Clipboard clipboard) throws IOException {
+ if (!(clipboard instanceof CuboidClipboard)) {
+ List cuboidList = new ArrayList<>();
+ new CuboidCreator(clipboard).forEachRemaining(cuboidList::add);
+ clipboard = new CuboidClipboard(clipboard, cuboidList, new HashMap<>());
+ }
+ CuboidClipboard cuboidClipboard = (CuboidClipboard) clipboard;
+
+ Region region = clipboard.getRegion();
+ BlockVector3 origin = clipboard.getOrigin();
+ BlockVector3 min = region.getMinimumPoint();
+ BlockVector3 offset = min.subtract(origin);
+
+ outputStream.writeLazyCompoundTag("Schematic", out -> {
+ out.writeNamedTag("DataVersion", WorldEdit.getInstance().getPlatformManager().queryCapability(Capability.WORLD_EDITING).getDataVersion());
+ out.writeNamedTag("Version", CURRENT_VERSION);
+ List bs = new ArrayList<>();
+ writeVarInt(region.getWidth(), bs);
+ writeVarInt(region.getHeight(), bs);
+ writeVarInt(region.getLength(), bs);
+ writeVarInt(min.getBlockX(), bs);
+ writeVarInt(min.getBlockY(), bs);
+ writeVarInt(min.getBlockZ(), bs);
+ writeVarInt(offset.getBlockX(), bs);
+ writeVarInt(offset.getBlockY(), bs);
+ writeVarInt(offset.getBlockZ(), bs);
+ byte[] bsArray = new byte[bs.size()];
+ for (int i = 0; i < bsArray.length; i++) {
+ bsArray[i] = bs.get(i);
+ }
+ out.writeNamedTag("SizeMinOffset", new ByteArrayTag(bsArray));
+
+ List cuboids = cuboidClipboard.getCuboids();
+ Map> cuboidMap = new HashMap<>();
+ for (Cuboid cuboid : cuboids) {
+ cuboidMap.computeIfAbsent(cuboid.getBlock(), k -> new ArrayList<>()).add(cuboid);
+ }
+
+ out.writeLazyCompoundTag("Cuboids", out1 -> {
+ BlockState mostBytes = null;
+ int mostBytesSize = 0;
+
+ Map cuboidBytes = new HashMap<>();
+ for (Map.Entry> entry : cuboidMap.entrySet()) {
+ List bytes = new ArrayList<>();
+ writeVarInt(cuboidClipboard.getOrder().getOrDefault(entry.getKey(), 0), bytes);
+ for (Cuboid cuboid : entry.getValue()) {
+ writeVarInt(cuboid.getOrigin().getBlockX(), bytes);
+ writeVarInt(cuboid.getOrigin().getBlockY(), bytes);
+ writeVarInt(cuboid.getOrigin().getBlockZ(), bytes);
+ if (cuboid.getSize().equals(BlockVector3.ONE)) {
+ writeVarInt(0, bytes);
+ } else if (cuboid.getSize().getBlockX() == cuboid.getSize().getBlockY() && cuboid.getSize().getBlockX() == cuboid.getSize().getBlockZ()) {
+ writeVarInt(cuboid.getSize().getBlockX(), bytes);
+ writeVarInt(0, bytes);
+ } else {
+ writeVarInt(cuboid.getSize().getBlockX(), bytes);
+ writeVarInt(cuboid.getSize().getBlockY(), bytes);
+ writeVarInt(cuboid.getSize().getBlockZ(), bytes);
+ }
+ }
+ byte[] bytesArray = new byte[bytes.size()];
+ for (int i = 0; i < bytesArray.length; i++) {
+ bytesArray[i] = bytes.get(i);
+ }
+ cuboidBytes.put(entry.getKey(), bytesArray);
+
+ if (mostBytes == null || bytesArray.length > mostBytesSize) {
+ mostBytes = entry.getKey();
+ mostBytesSize = bytesArray.length;
+ }
+ }
+ System.out.println("Most bytes: " + mostBytes.getAsString() + " (" + mostBytesSize + " bytes)");
+ cuboidBytes.remove(mostBytes);
+ out1.writeNamedTag("BASE", mostBytes.getAsString());
+ for (Map.Entry entry : cuboidBytes.entrySet()) {
+ out1.writeLazyCompoundTag(entry.getKey().getAsString().substring(10), out2 -> {
+ out2.writeTagPayload(new ByteArrayTag(entry.getValue()));
+ });
+ }
+ });
+ });
+ }
+
+ private static void writeVarInt(int value, List bytes) {
+ while (true) {
+ if (value < 128) {
+ bytes.add((byte) value);
+ return;
+ } else {
+ bytes.add((byte) (value & 127 | 128));
+ value >>>= 7;
+ }
+ }
+ }
+
+ @Override
+ public void close() throws IOException {
+ outputStream.close();
+ }
+}