From dfd4a59ebe47a520514648a63e00a977c945239b 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 8dcb15fb8..7e1ee875e 100644 --- a/src/main/java/org/bukkit/Location.java +++ b/src/main/java/org/bukkit/Location.java @@ -10,7 +10,6 @@ import org.bukkit.util.Vector; // 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; @@ -558,6 +557,18 @@ public class Location implements Cloneable, ConfigurationSerializable { blockLoc.setZ(getBlockZ()); return blockLoc; } + + // Paper Start + + /** + * @return The block key for this location's block location. + * @see Block#getBlockKey() + */ + public long toBlockKey() { + return ((long)getBlockX() & 0x7FFFFFF) | (((long)getBlockZ() & 0x7FFFFFF) << 27) | ((long)getBlockY() << 54); + } + // 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 724088ec0..d4bfbad33 100644 --- a/src/main/java/org/bukkit/World.java +++ b/src/main/java/org/bukkit/World.java @@ -73,6 +73,37 @@ public interface World extends PluginMessageRecipient, Metadatable { */ public Block getBlockAt(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 Location#toBlockKey() + * @see Block#getBlockKey() + */ + public default Block getBlockAtKey(long key) { + int x = (int) ((key << 37) >> 37); + int y = (int) (key >>> 54); + int z = (int) ((key << 10) >> 37); + 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 Location#toBlockKey() + * @see Block#getBlockKey() + */ + public default Location getLocationAtKey(long key) { + int x = (int) ((key << 37) >> 37); + int y = (int) (key >>> 54); + int z = (int) ((key << 10) >> 37); + return new Location(this, x, y, z); + } + // Paper end + /** * Gets the y coordinate of the lowest block at this position such that the * block and all blocks above it are transparent for lighting purposes. diff --git a/src/main/java/org/bukkit/block/Block.java b/src/main/java/org/bukkit/block/Block.java index 238de6f0a..d700df538 100644 --- a/src/main/java/org/bukkit/block/Block.java +++ b/src/main/java/org/bukkit/block/Block.java @@ -139,6 +139,30 @@ public interface Block extends Metadatable { */ int getZ(); + // Paper Start + + /** + * Returns this block's coordinates packed into a long value + *

+ * The return value can be computed as follows: + *

+ * {@code long value = ((long)getX() & 0x7FFFFFF) | (((long)getZ() & 0x7FFFFFF) << 27) | ((long)getY() << 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 + */ + public default long getBlockKey() { + return ((long)getX() & 0x7FFFFFF) | (((long)getZ() & 0x7FFFFFF) << 27) | ((long)getY() << 54); + } + // Paper End + /** * Gets the Location of the block * -- 2.18.0