From 28a0239437739b5551cf9ded160a7a305ff05991 Mon Sep 17 00:00:00 2001 From: Jordan Date: Thu, 24 Feb 2022 10:32:45 +0100 Subject: [PATCH] Fix clipboards to allow proper heights by allowing extended CuboidRegion heights (#1624) * Fix clipboards to allow proper heights by allowing extended CuboidRegion heights Fixes #1534 * Add @since * Fix javadoc comment Co-authored-by: Alex --- .../fastasyncworldedit/bukkit/FaweBukkit.java | 2 +- .../bukkit/util/MinecraftVersion.java | 35 ++++++++++----- .../bukkit/BukkitServerInterface.java | 4 +- .../bukkit/adapter/BukkitImplLoader.java | 2 +- .../clipboard/DiskOptimizedClipboard.java | 40 +++++++---------- .../extent/clipboard/SimpleClipboard.java | 7 ++- .../java/com/sk89q/worldedit/EditSession.java | 7 ++- .../worldedit/extent/clipboard/Clipboard.java | 5 +-- .../sk89q/worldedit/regions/CuboidRegion.java | 43 ++++++++++++++++++- 9 files changed, 98 insertions(+), 47 deletions(-) diff --git a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/FaweBukkit.java b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/FaweBukkit.java index 7e60a05cb..71fee08ab 100644 --- a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/FaweBukkit.java +++ b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/FaweBukkit.java @@ -83,7 +83,7 @@ public class FaweBukkit implements IFawe, Listener { Bukkit.getServer().shutdown(); } - MinecraftVersion version = new MinecraftVersion(); + MinecraftVersion version = MinecraftVersion.getCurrent(); chunksStretched = version.isEqualOrHigherThan(MinecraftVersion.NETHER); diff --git a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/util/MinecraftVersion.java b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/util/MinecraftVersion.java index 43fa6b0b6..a3375c8fc 100644 --- a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/util/MinecraftVersion.java +++ b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/util/MinecraftVersion.java @@ -13,6 +13,7 @@ public class MinecraftVersion implements Comparable { public static final MinecraftVersion NETHER = new MinecraftVersion(1, 16); public static final MinecraftVersion CAVES_17 = new MinecraftVersion(1, 17); public static final MinecraftVersion CAVES_18 = new MinecraftVersion(1, 18); + private static MinecraftVersion current = null; private final int major; private final int minor; @@ -57,6 +58,29 @@ public class MinecraftVersion implements Comparable { this.release = Integer.parseInt(versionParts[2].substring(1)); } + /** + * Get the minecraft version that the server is currently running + * + * @since TODO + */ + public static MinecraftVersion getCurrent() { + if (current == null) { + return current = new MinecraftVersion(); + } + return current; + } + + /** + * Determines the server version based on the CraftBukkit package path, e.g. {@code org.bukkit.craftbukkit.v1_16_R3}, + * where v1_16_R3 is the resolved version. + * + * @return The package version. + */ + private static String getPackageVersion() { + String fullPackagePath = Bukkit.getServer().getClass().getPackage().getName(); + return fullPackagePath.substring(fullPackagePath.lastIndexOf('.') + 1); + } + /** * @param other The other version to compare against. * @return {@code true} if this version is equal to the other version. @@ -145,15 +169,4 @@ public class MinecraftVersion implements Comparable { return major + "." + minor + "." + release; } - /** - * Determines the server version based on the CraftBukkit package path, e.g. {@code org.bukkit.craftbukkit.v1_16_R3}, - * where v1_16_R3 is the resolved version. - * - * @return The package version. - */ - private static String getPackageVersion() { - String fullPackagePath = Bukkit.getServer().getClass().getPackage().getName(); - return fullPackagePath.substring(fullPackagePath.lastIndexOf('.') + 1); - } - } diff --git a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitServerInterface.java b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitServerInterface.java index 602ec139b..89bbaa0cf 100644 --- a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitServerInterface.java +++ b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitServerInterface.java @@ -282,12 +282,12 @@ public class BukkitServerInterface extends AbstractPlatform implements MultiUser @Override public int versionMinY() { - return new MinecraftVersion().isEqualOrHigherThan(MinecraftVersion.CAVES_18) ? -64 : 0; + return MinecraftVersion.getCurrent().isEqualOrHigherThan(MinecraftVersion.CAVES_18) ? -64 : 0; } @Override public int versionMaxY() { - return new MinecraftVersion().isEqualOrHigherThan(MinecraftVersion.CAVES_18) ? 319 : 255; + return MinecraftVersion.getCurrent().isEqualOrHigherThan(MinecraftVersion.CAVES_18) ? 319 : 255; } //FAWE end } diff --git a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/BukkitImplLoader.java b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/BukkitImplLoader.java index 11cee4f14..5cf783350 100644 --- a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/BukkitImplLoader.java +++ b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/BukkitImplLoader.java @@ -40,7 +40,7 @@ public class BukkitImplLoader { private static final Logger LOGGER = LogManagerCompat.getLogger(); private final List adapterCandidates = new ArrayList<>(); - private final String minorMCVersion = String.valueOf(new MinecraftVersion().getMinor()); + private final String minorMCVersion = String.valueOf(MinecraftVersion.getCurrent().getMinor()); private int zeroth = 0; private String customCandidate; diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/DiskOptimizedClipboard.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/DiskOptimizedClipboard.java index 9a9ed58d7..69aa98b7e 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/DiskOptimizedClipboard.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/DiskOptimizedClipboard.java @@ -27,7 +27,6 @@ import com.sk89q.worldedit.world.block.BlockTypes; import org.apache.logging.log4j.Logger; import javax.annotation.Nullable; -import java.io.Closeable; import java.io.DataInputStream; import java.io.File; import java.io.FileInputStream; @@ -51,7 +50,7 @@ import java.util.stream.Collectors; * - Uses an auto closable RandomAccessFile for getting / setting id / data * - I don't know how to reduce nbt / entities to O(2) complexity, so it is stored in memory. */ -public class DiskOptimizedClipboard extends LinearClipboard implements Closeable { +public class DiskOptimizedClipboard extends LinearClipboard { private static final Logger LOGGER = LogManagerCompat.getLogger(); @@ -139,7 +138,7 @@ public class DiskOptimizedClipboard extends LinearClipboard implements Closeable if (braf.length() - HEADER_SIZE == ((long) getVolume() << 1) + (long) ((getHeight() >> 2) + 1) * ((getLength() >> 2) + 1) * ((getWidth() >> 2) + 1)) { hasBiomes = true; } - getOffset(); + getAndSetOffsetAndOrigin(); } catch (IOException e) { throw new RuntimeException(e); } @@ -267,14 +266,8 @@ public class DiskOptimizedClipboard extends LinearClipboard implements Closeable public BlockArrayClipboard toClipboard() { try { - CuboidRegion region = new CuboidRegion( - BlockVector3.at(0, 0, 0), - BlockVector3.at(getWidth() - 1, getHeight() - 1, getLength() - 1) - ); - int offsetX = byteBuffer.getShort(16); - int offsetY = byteBuffer.getShort(18); - int offsetZ = byteBuffer.getShort(20); - region.shift(BlockVector3.at(offsetX, offsetY, offsetZ)); + Region region = getRegion(); + region.shift(offset); BlockArrayClipboard clipboard = new BlockArrayClipboard(region, this); clipboard.setOrigin(getOrigin().add(offset)); return clipboard; @@ -285,20 +278,13 @@ public class DiskOptimizedClipboard extends LinearClipboard implements Closeable } @Override - public BlockVector3 getOrigin() { - int ox = byteBuffer.getShort(10); - int oy = byteBuffer.getShort(12); - int oz = byteBuffer.getShort(14); - return BlockVector3.at(ox, oy, oz).subtract(offset); - } - - @Override - public void setOrigin(BlockVector3 offset) { - super.setOrigin(offset); + public void setOrigin(BlockVector3 origin) { + super.setOrigin(origin); + origin = origin.subtract(offset); try { - byteBuffer.putShort(10, (short) offset.getBlockX()); - byteBuffer.putShort(12, (short) offset.getBlockY()); - byteBuffer.putShort(14, (short) offset.getBlockZ()); + byteBuffer.putShort(10, (short) origin.getBlockX()); + byteBuffer.putShort(12, (short) origin.getBlockY()); + byteBuffer.putShort(14, (short) origin.getBlockZ()); } catch (Throwable e) { e.printStackTrace(); } @@ -316,11 +302,15 @@ public class DiskOptimizedClipboard extends LinearClipboard implements Closeable } } - private void getOffset() { + private void getAndSetOffsetAndOrigin() { int x = byteBuffer.getShort(16); int y = byteBuffer.getShort(18); int z = byteBuffer.getShort(20); super.setOffset(BlockVector3.at(x, y, z)); + int ox = byteBuffer.getShort(10); + int oy = byteBuffer.getShort(12); + int oz = byteBuffer.getShort(14); + super.setOrigin(BlockVector3.at(ox, oy, oz).add(offset)); } @Override diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/SimpleClipboard.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/SimpleClipboard.java index b3494e6d2..4e6646efb 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/SimpleClipboard.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/SimpleClipboard.java @@ -55,7 +55,12 @@ public abstract class SimpleClipboard implements Clipboard { @Override public Region getRegion() { - return new CuboidRegion(BlockVector3.ZERO, BlockVector3.at(getWidth() - 1, getHeight() - 1, getLength() - 1)); + return new CuboidRegion( + null, + BlockVector3.ZERO, + BlockVector3.at(getWidth() - 1, getHeight() - 1, getLength() - 1), + false + ); } @Override diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java b/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java index d54548755..5bd31cb83 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java @@ -61,6 +61,7 @@ import com.sk89q.worldedit.entity.BaseEntity; import com.sk89q.worldedit.entity.Entity; import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.extension.platform.Actor; +import com.sk89q.worldedit.extension.platform.Capability; import com.sk89q.worldedit.extent.AbstractDelegateExtent; import com.sk89q.worldedit.extent.ChangeSetExtent; import com.sk89q.worldedit.extent.Extent; @@ -263,8 +264,10 @@ public class EditSession extends PassthroughExtent implements AutoCloseable { this.limit = builder.getLimit().copy(); this.actor = builder.getActor(); this.changeSet = builder.getChangeTask(); - this.minY = world.getMinY(); - this.maxY = world.getMaxY(); + this.minY = world != null ? world.getMinY() : + WorldEdit.getInstance().getPlatformManager().queryCapability(Capability.WORLD_EDITING).versionMinY(); + this.maxY = world != null ? world.getMaxY() : + WorldEdit.getInstance().getPlatformManager().queryCapability(Capability.WORLD_EDITING).versionMaxY(); this.blockBag = builder.getBlockBag(); this.history = changeSet != null; this.relighter = builder.getRelighter(); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/Clipboard.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/Clipboard.java index c4d940d7a..b2472d9c2 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/Clipboard.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/Clipboard.java @@ -340,8 +340,7 @@ public interface Clipboard extends Extent, Iterable, Closeable, Fl copy.setTransform(transform); } copy.setCopyingBiomes(this.hasBiomes()); - if (extent instanceof EditSession) { - EditSession editSession = (EditSession) extent; + if (extent instanceof EditSession editSession) { Mask sourceMask = editSession.getSourceMask(); if (sourceMask != null) { new MaskTraverser(sourceMask).reset(extent); @@ -393,7 +392,7 @@ public interface Clipboard extends Extent, Iterable, Closeable, Fl continue; } if (pos.getY() < extent.getMinY()) { - throw new RuntimeException("Y-Position cannot be less than 0!"); + throw new RuntimeException("Y-Position cannot be less than the extent's minimum Y!"); } extent.setBlock(xx, yy, zz, block); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/regions/CuboidRegion.java b/worldedit-core/src/main/java/com/sk89q/worldedit/regions/CuboidRegion.java index 82e89aee7..a15385962 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/regions/CuboidRegion.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/regions/CuboidRegion.java @@ -85,6 +85,30 @@ public class CuboidRegion extends AbstractRegion implements FlatRegion { recalculate(); } + //FAWE start - allow region to be created without clamping Y + /** + * Construct a new instance of this cuboid using two corners of the cuboid. + * + * @param world the world + * @param pos1 the first position + * @param pos2 the second position + * @param clampY if the min/max Y of the region should be clamped to the world + * @since TODO + */ + public CuboidRegion(World world, BlockVector3 pos1, BlockVector3 pos2, boolean clampY) { + super(world); + checkNotNull(pos1); + checkNotNull(pos2); + this.pos1 = pos1; + this.pos2 = pos2; + if (clampY) { + recalculate(); + } else { + recalculateNoClamp(); + } + } + //FAWE end + /** * Get the first cuboid-defining corner. * @@ -128,7 +152,7 @@ public class CuboidRegion extends AbstractRegion implements FlatRegion { } /** - * Clamps the cuboid according to boundaries of the world. + * Sets the cached min and max x/y/z and clamps Y to world y min/max */ protected void recalculate() { if (pos1 == null || pos2 == null) { @@ -144,6 +168,23 @@ public class CuboidRegion extends AbstractRegion implements FlatRegion { maxZ = Math.max(pos1.getZ(), pos2.getZ()); } + //FAWE start - allow region to be created without clamping Y + /** + * Sets the cached min and max x/y/z + */ + protected void recalculateNoClamp() { + if (pos1 == null || pos2 == null) { + return; + } + minX = Math.min(pos1.getX(), pos2.getX()); + minY = Math.min(pos1.getY(), pos2.getY()); + minZ = Math.min(pos1.getZ(), pos2.getZ()); + maxX = Math.max(pos1.getX(), pos2.getX()); + maxY = Math.max(pos1.getY(), pos2.getY()); + maxZ = Math.max(pos1.getZ(), pos2.getZ()); + } + //FAWE end + /** * Get a region that contains the faces of this cuboid. *