Signed-off-by: yoyosource <yoyosource@nidido.de>
Dieser Commit ist enthalten in:
Ursprung
7494b8abea
Commit
6fedbac3f9
@ -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 <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
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<String> 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<String> getFileExtensions() {
|
||||||
|
return new HashSet<>(Arrays.asList("cschem"));
|
||||||
|
}
|
||||||
|
}
|
@ -19,33 +19,45 @@
|
|||||||
|
|
||||||
package de.steamwar.bausystem.features.cuboid;
|
package de.steamwar.bausystem.features.cuboid;
|
||||||
|
|
||||||
|
import com.sk89q.worldedit.math.BlockVector3;
|
||||||
|
import com.sk89q.worldedit.world.block.BlockState;
|
||||||
import lombok.ToString;
|
import lombok.ToString;
|
||||||
|
|
||||||
@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 Cuboid(BlockVector3 origin, BlockState block) {
|
||||||
public int y;
|
this.x = origin.getBlockX();
|
||||||
public int z;
|
this.y = origin.getBlockY();
|
||||||
public int dx;
|
this.z = origin.getBlockZ();
|
||||||
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;
|
|
||||||
|
|
||||||
this.dx = 1;
|
this.dx = 1;
|
||||||
this.dy = 1;
|
this.dy = 1;
|
||||||
this.dz = 1;
|
this.dz = 1;
|
||||||
|
|
||||||
this.blockData = blockData;
|
this.block = block;
|
||||||
}
|
}
|
||||||
|
|
||||||
public long size() {
|
public long size() {
|
||||||
return (long) dx * (long) dy * (long) dz;
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
@ -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 <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
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<Location, Location> 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);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
@ -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 <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
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<Cuboid> cuboids;
|
||||||
|
private Map<BlockState, Integer> order;
|
||||||
|
|
||||||
|
public CuboidClipboard(Clipboard parent, List<Cuboid> cuboids, Map<BlockState, Integer> 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;
|
||||||
|
}
|
||||||
|
}
|
@ -19,182 +19,77 @@
|
|||||||
|
|
||||||
package de.steamwar.bausystem.features.cuboid;
|
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.BauSystem;
|
||||||
import de.steamwar.bausystem.shared.Pair;
|
|
||||||
import de.steamwar.bausystem.utils.WorldEditUtils;
|
import de.steamwar.bausystem.utils.WorldEditUtils;
|
||||||
import de.steamwar.command.SWCommand;
|
import de.steamwar.command.SWCommand;
|
||||||
import lombok.ToString;
|
import de.steamwar.linkage.Linked;
|
||||||
import org.bukkit.Axis;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.Location;
|
|
||||||
import org.bukkit.Material;
|
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.scheduler.BukkitRunnable;
|
import org.bukkit.scheduler.BukkitRunnable;
|
||||||
import org.bukkit.util.Vector;
|
|
||||||
|
|
||||||
import java.util.*;
|
import java.io.IOException;
|
||||||
import java.util.function.Supplier;
|
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 {
|
public class CuboidCommand extends SWCommand {
|
||||||
|
|
||||||
|
static {
|
||||||
|
ClipboardFormats.registerClipboardFormat(new CSchemClipboardFormat());
|
||||||
|
}
|
||||||
|
|
||||||
public CuboidCommand() {
|
public CuboidCommand() {
|
||||||
super("cuboid");
|
super("cuboid");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Register
|
@Register
|
||||||
public void genericCommand(Player player) {
|
public void onCommand(Player player) {
|
||||||
Pair<Location, Location> selection = WorldEditUtils.getSelection(player);
|
Clipboard clipboard = WorldEditUtils.getClipboard(player);
|
||||||
if (selection == null) {
|
if (clipboard == null) {
|
||||||
player.sendMessage("§cDu musst erst eine Auswahl treffen!");
|
player.sendMessage("§cDu hast keine Schematic geladen!");
|
||||||
return;
|
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<Vector, Material> 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<Vector> left = new ArrayList<>();
|
|
||||||
left.add(minVec);
|
|
||||||
|
|
||||||
long time = System.currentTimeMillis();
|
long time = System.currentTimeMillis();
|
||||||
List<BlockCuboid> cuboids = new ArrayList<>();
|
CuboidCreator4 cuboidCreator4 = new CuboidCreator4(clipboard);
|
||||||
runTickEfficient(left::isEmpty, () -> {
|
runAsync(cuboidCreator4, cuboids -> {
|
||||||
System.out.println(left.size());
|
long t2 = System.currentTimeMillis() - time;
|
||||||
Vector current = left.remove(0);
|
player.sendMessage("§aEs wurden " + cuboids.size() + " Cuboids erstellt!");
|
||||||
if (current.getX() > maxVec.getX() || current.getY() > maxVec.getY() || current.getZ() > maxVec.getZ()) {
|
player.sendMessage("§aDas hat " + t2 + "ms gedauert!");
|
||||||
return;
|
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"));
|
||||||
BlockCuboid cuboid = new BlockCuboid(current, blocks.get(current));
|
} catch (IOException e) {
|
||||||
expand(cuboid, maxVec, blocks);
|
}
|
||||||
cuboids.add(cuboid);
|
player.sendMessage("§aDie Größe der Schematic beträgt " + size.get() + " Bytes!");
|
||||||
|
|
||||||
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);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void runTickEfficient(Supplier<Boolean> finished, Runnable next, Runnable finishedCallback) {
|
private <T> void runAsync(Iterator<T> iterator, Consumer<List<T>> result) {
|
||||||
new BukkitRunnable() {
|
new BukkitRunnable() {
|
||||||
|
private final List<T> list = new ArrayList<>();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
if (finished.get()) {
|
iterator.forEachRemaining(list::add);
|
||||||
cancel();
|
Bukkit.getScheduler().runTaskLater(BauSystem.getInstance(), () -> {
|
||||||
finishedCallback.run();
|
result.accept(list);
|
||||||
return;
|
}, 1);
|
||||||
}
|
}
|
||||||
long time = System.currentTimeMillis();
|
}.runTaskAsynchronously(BauSystem.getInstance());
|
||||||
while (System.currentTimeMillis() - time < 50) {
|
|
||||||
if (finished.get()) {
|
|
||||||
cancel();
|
|
||||||
finishedCallback.run();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
next.run();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}.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<Vector, Material> blocks) {
|
|
||||||
List<Axis> 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<Vector, Material> 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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,18 +17,17 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package de.steamwar.bausystem.features.cuboid.clipboard;
|
package de.steamwar.bausystem.features.cuboid;
|
||||||
|
|
||||||
import com.sk89q.worldedit.extent.clipboard.Clipboard;
|
import com.sk89q.worldedit.extent.clipboard.Clipboard;
|
||||||
import com.sk89q.worldedit.math.BlockVector3;
|
import com.sk89q.worldedit.math.BlockVector3;
|
||||||
import com.sk89q.worldedit.world.block.BlockState;
|
import com.sk89q.worldedit.world.block.BlockState;
|
||||||
import lombok.ToString;
|
|
||||||
import org.bukkit.Axis;
|
import org.bukkit.Axis;
|
||||||
import org.bukkit.util.Vector;
|
import org.bukkit.util.Vector;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
public class CuboidCreator implements Iterator<CuboidCreator.Cuboid> {
|
public class CuboidCreator implements Iterator<Cuboid> {
|
||||||
|
|
||||||
private static final List<Axis[]> AXES = Arrays.asList(
|
private static final List<Axis[]> AXES = Arrays.asList(
|
||||||
new Axis[]{Axis.X, Axis.Y, Axis.Z},
|
new Axis[]{Axis.X, Axis.Y, Axis.Z},
|
||||||
@ -86,9 +85,9 @@ public class CuboidCreator implements Iterator<CuboidCreator.Cuboid> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
left.add(BlockVector3.at(origin.getBlockX() + cuboid.dx + 1, origin.getBlockY(), origin.getBlockZ()));
|
left.add(BlockVector3.at(origin.getBlockX() + cuboid.dx, 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() + cuboid.dy, origin.getBlockZ()));
|
||||||
left.add(BlockVector3.at(origin.getBlockX(), origin.getBlockY(), origin.getBlockZ() + cuboid.dz + 1));
|
left.add(BlockVector3.at(origin.getBlockX(), origin.getBlockY(), origin.getBlockZ() + cuboid.dz));
|
||||||
return cuboid;
|
return cuboid;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -117,7 +116,7 @@ public class CuboidCreator implements Iterator<CuboidCreator.Cuboid> {
|
|||||||
if (direction.getX() == 1) {
|
if (direction.getX() == 1) {
|
||||||
for (int y = cuboid.y; y < cuboid.y + cuboid.dy; y++) {
|
for (int y = cuboid.y; y < cuboid.y + cuboid.dy; y++) {
|
||||||
for (int z = cuboid.z; z < cuboid.z + cuboid.dz; z++) {
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -125,7 +124,7 @@ public class CuboidCreator implements Iterator<CuboidCreator.Cuboid> {
|
|||||||
} else if (direction.getY() == 1) {
|
} else if (direction.getY() == 1) {
|
||||||
for (int x = cuboid.x; x < cuboid.x + cuboid.dx; x++) {
|
for (int x = cuboid.x; x < cuboid.x + cuboid.dx; x++) {
|
||||||
for (int z = cuboid.z; z < cuboid.z + cuboid.dz; z++) {
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -133,7 +132,7 @@ public class CuboidCreator implements Iterator<CuboidCreator.Cuboid> {
|
|||||||
} else if (direction.getZ() == 1) {
|
} else if (direction.getZ() == 1) {
|
||||||
for (int x = cuboid.x; x < cuboid.x + cuboid.dx; x++) {
|
for (int x = cuboid.x; x < cuboid.x + cuboid.dx; x++) {
|
||||||
for (int y = cuboid.y; y < cuboid.y + cuboid.dy; y++) {
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -148,43 +147,4 @@ public class CuboidCreator implements Iterator<CuboidCreator.Cuboid> {
|
|||||||
}
|
}
|
||||||
return true;
|
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -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 <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
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<Cuboid> {
|
||||||
|
|
||||||
|
private static final List<Axis[]> 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<BlockState, Set<BlockVector3>> 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<BlockState, Set<BlockVector3>> entry : reverseBlocks.entrySet()) {
|
||||||
|
BlockState block = entry.getKey();
|
||||||
|
Set<BlockVector3> 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<Axis> axes, Set<BlockVector3> 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<BlockVector3> 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;
|
||||||
|
}
|
||||||
|
}
|
@ -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 <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
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<Cuboid> {
|
||||||
|
|
||||||
|
private static final List<Axis[]> 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<String> invisible = new HashSet<>();
|
||||||
|
static {
|
||||||
|
for (Material value : Material.values()) {
|
||||||
|
if (!value.isOccluding() || value.isAir()) {
|
||||||
|
invisible.add("minecraft:" + value.name().toLowerCase());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Set<BlockVector3> invisibleBlocks = new HashSet<>();
|
||||||
|
private Map<BlockState, Set<BlockVector3>> 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<BlockState, Set<BlockVector3>> entry : reverseBlocks.entrySet()) {
|
||||||
|
BlockState block = entry.getKey();
|
||||||
|
Set<BlockVector3> 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<Axis> axes, Set<BlockVector3> 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<BlockVector3> 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;
|
||||||
|
}
|
||||||
|
}
|
@ -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 <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
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<Cuboid> {
|
||||||
|
|
||||||
|
private static final List<Axis[]> 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<BlockState> invisibleOrder = new ArrayList<>();
|
||||||
|
private Map<BlockState, Set<BlockState>> invisible = new HashMap<>();
|
||||||
|
|
||||||
|
private Map<BlockVector3, BlockState> blocks = new HashMap<>();
|
||||||
|
private Map<BlockState, Set<BlockVector3>> 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<BlockState, Integer> applyOrder() {
|
||||||
|
Map<BlockState, Integer> 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<BlockState, Set<BlockVector3>> entry : reverseBlocks.entrySet()) {
|
||||||
|
BlockState block = entry.getKey();
|
||||||
|
List<BlockVector3> 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<Axis> axes, Set<BlockVector3> 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<BlockVector3> blocks) {
|
||||||
|
Set<BlockState> 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;
|
||||||
|
}
|
||||||
|
}
|
@ -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 <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
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<String, List<TypedCuboid>> 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<String, Tag> 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<String, Tag> cuboidMap = new HashMap<>();
|
|
||||||
for (Map.Entry<String, List<TypedCuboid>> 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<Byte> 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<Byte> bytes) {
|
|
||||||
while (true) {
|
|
||||||
if (value < 128) {
|
|
||||||
bytes.add((byte) value);
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
bytes.add((byte) (value & 127 | 128));
|
|
||||||
value >>>= 7;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -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 <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
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<Axis[]> 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<CuboidSchematic> consumer) {
|
|
||||||
// Setup
|
|
||||||
Pos playerPos = new Pos(player.getLocation());
|
|
||||||
Pos offset = min.sub(playerPos);
|
|
||||||
Map<Pos, String> blocks = CuboidSchematicWriter.getBlocks(player, min, max); // Needs to be optimized
|
|
||||||
Map<String, Set<Pos>> reverseBlocks = reverse(blocks);
|
|
||||||
|
|
||||||
// Create CuboidSchematic
|
|
||||||
CuboidSchematic schematic = new CuboidSchematic(offset, max.sub(min));
|
|
||||||
|
|
||||||
// Create Cuboids
|
|
||||||
long time = System.currentTimeMillis();
|
|
||||||
List<Pos> 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<Pos> 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<Boolean> 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<Pos, String> getBlocks(Player player, Pos min, Pos max) {
|
|
||||||
Map<Pos, String> 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 <K, V> Map<V, Set<K>> reverse(Map<K, V> input) {
|
|
||||||
Map<V, Set<K>> output = new HashMap<>();
|
|
||||||
for (Map.Entry<K, V> entry : input.entrySet()) {
|
|
||||||
output.computeIfAbsent(entry.getValue(), k -> new HashSet<>()).add(entry.getKey());
|
|
||||||
}
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void expand(TypedCuboid cuboid, List<Axis> axes, Map<String, Set<Pos>> 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<String, Set<Pos>> reverseBlocks) {
|
|
||||||
Set<Pos> 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;
|
|
||||||
}
|
|
||||||
}
|
|
@ -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 <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
@ -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 <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
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!");
|
|
||||||
}
|
|
||||||
}
|
|
@ -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 <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
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<Cuboid> 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<Byte> 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<Cuboid> cuboids = cuboidClipboard.getCuboids();
|
||||||
|
Map<BlockState, List<Cuboid>> 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<BlockState, byte[]> cuboidBytes = new HashMap<>();
|
||||||
|
for (Map.Entry<BlockState, List<Cuboid>> entry : cuboidMap.entrySet()) {
|
||||||
|
List<Byte> 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<BlockState, byte[]> entry : cuboidBytes.entrySet()) {
|
||||||
|
out1.writeLazyCompoundTag(entry.getKey().getAsString().substring(10), out2 -> {
|
||||||
|
out2.writeTagPayload(new ByteArrayTag(entry.getValue()));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void writeVarInt(int value, List<Byte> 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();
|
||||||
|
}
|
||||||
|
}
|
In neuem Issue referenzieren
Einen Benutzer sperren