From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Spottedleaf Date: Tue, 14 Aug 2018 21:42:10 -0700 Subject: [PATCH] Allow Blocks to be accessed via a long key The key can be retrieved via methods Location#toBlockKey() and Block#getBlockKey() World provides lookup for blocks by long key via method World#getBlockAtKey(long) The formatting for the key is as follows: 10 bit y|27 bit z|27 bit x The y value is considered unsigned while z and x are considered two's complement Y range: [0, 1023] X, Z range: [-67 108 864, 67 108 863] diff --git a/src/main/java/org/bukkit/Location.java b/src/main/java/org/bukkit/Location.java index 56fd66a3fb5f6e33812d2981cd192d317453a0f5..12e1733d06471d0c2253ae846ee93a09140843cc 100644 --- a/src/main/java/org/bukkit/Location.java +++ b/src/main/java/org/bukkit/Location.java @@ -15,7 +15,6 @@ import org.jetbrains.annotations.Nullable; // Paper start import java.util.Collection; -import java.util.Collections; import java.util.function.Predicate; import org.bukkit.entity.Entity; import org.bukkit.entity.LivingEntity; @@ -610,6 +609,19 @@ public class Location implements Cloneable, ConfigurationSerializable, io.paperm blockLoc.setZ(getBlockZ()); return blockLoc; } + + // Paper start + /** + * @return The block key for this location's block location. + * @see Block#getBlockKey(int, int, int) + * @deprecated only encodes y block ranges from -512 to 511 and represents an already changed implementation detail + */ + @Deprecated(since = "1.18.1") + public long toBlockKey() { + return Block.getBlockKey(getBlockX(), getBlockY(), getBlockZ()); + } + // Paper end + /** * @return A new location where X/Y/Z are the center of the block */ diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java index 11362777d834cad2265984c7aa493358105cbf68..c474f6f0f1d758507f53c6f1ffbe3e26883e1425 100644 --- a/src/main/java/org/bukkit/World.java +++ b/src/main/java/org/bukkit/World.java @@ -99,6 +99,41 @@ public interface World extends RegionAccessor, WorldInfo, PluginMessageRecipient @NotNull public Block getBlockAt(@NotNull Location location); + // Paper start + /** + * Gets the {@link Block} at the given block key + * + * @param key The block key. See {@link Block#getBlockKey()} + * @return Block at the key + * @see Block#getBlockKey(int, int, int) + * @deprecated only encodes y block ranges from -512 to 511 and represents an already changed implementation detail + */ + @NotNull + @Deprecated(since = "1.18.1") + public default Block getBlockAtKey(long key) { + int x = Block.getBlockKeyX(key); + int y = Block.getBlockKeyY(key); + int z = Block.getBlockKeyZ(key); + return getBlockAt(x, y, z); + } + + /** + * Gets the {@link Location} at the given block key + * + * @param key The block key. See {@link Location#toBlockKey()} + * @return Location at the key + * @see Block#getBlockKey(int, int, int) + */ + @NotNull + @Deprecated(since = "1.18.1") + public default Location getLocationAtKey(long key) { + int x = Block.getBlockKeyX(key); + int y = Block.getBlockKeyY(key); + int z = Block.getBlockKeyZ(key); + return new Location(this, x, y, z); + } + // Paper end + /** * Gets the highest non-empty (impassable) block at the given coordinates. * diff --git a/src/main/java/org/bukkit/block/Block.java b/src/main/java/org/bukkit/block/Block.java index f3b3606dc5881e931853fc2631aad9ca9083474d..bb3cf2c5e2acbcd7cf53ad8551a5b11fa6104ada 100644 --- a/src/main/java/org/bukkit/block/Block.java +++ b/src/main/java/org/bukkit/block/Block.java @@ -156,6 +156,82 @@ public interface Block extends Metadatable, Translatable { */ int getZ(); + // Paper start + /** + * Returns this block's coordinates packed into a long value. + * Computed via: {@code Block.getBlockKey(this.getX(), this.getY(), this.getZ())} + * @see Block#getBlockKey(int, int, int) + * @return This block's x, y, and z coordinates packed into a long value + * @deprecated see {@link #getBlockKey(int, int, int)} + */ + @Deprecated(since = "1.18.1") + public default long getBlockKey() { + return Block.getBlockKey(this.getX(), this.getY(), this.getZ()); + } + + /** + * Returns the specified block coordinates packed into a long value + *

+ * The return value can be computed as follows: + *
+ * {@code long value = ((long)x & 0x7FFFFFF) | (((long)z & 0x7FFFFFF) << 27) | ((long)y << 54);} + *

+ * + *

+ * And may be unpacked as follows: + *
+ * {@code int x = (int) ((packed << 37) >> 37);} + *
+ * {@code int y = (int) (packed >> 54);} + *
+ * {@code int z = (int) ((packed << 10) >> 37);} + *

+ * + * @return This block's x, y, and z coordinates packed into a long value + * @deprecated only encodes y block ranges from -512 to 511 and represents an already changed implementation detail + */ + @Deprecated(since = "1.18.1") + public static long getBlockKey(int x, int y, int z) { + return ((long)x & 0x7FFFFFF) | (((long)z & 0x7FFFFFF) << 27) | ((long)y << 54); + } + + /** + * Returns the x component from the packed value. + * @param packed The packed value, as computed by {@link Block#getBlockKey(int, int, int)} + * @see Block#getBlockKey(int, int, int) + * @return The x component from the packed value. + * @deprecated see {@link #getBlockKey(int, int, int)} + */ + @Deprecated(since = "1.18.1") + public static int getBlockKeyX(long packed) { + return (int) ((packed << 37) >> 37); + } + + /** + * Returns the y component from the packed value. + * @param packed The packed value, as computed by {@link Block#getBlockKey(int, int, int)} + * @see Block#getBlockKey(int, int, int) + * @return The y component from the packed value. + * @deprecated see {@link #getBlockKey(int, int, int)} + */ + @Deprecated(since = "1.18.1") + public static int getBlockKeyY(long packed) { + return (int) (packed >> 54); + } + + /** + * Returns the z component from the packed value. + * @param packed The packed value, as computed by {@link Block#getBlockKey(int, int, int)} + * @see Block#getBlockKey(int, int, int) + * @return The z component from the packed value. + * @deprecated see {@link #getBlockKey(int, int, int)} + */ + @Deprecated(since = "1.18.1") + public static int getBlockKeyZ(long packed) { + return (int) ((packed << 10) >> 37); + } + // Paper end + /** * Gets the Location of the block *