Paper/patches/api/0138-Allow-Blocks-to-be-accessed-via-a-long-key.patch
2021-06-19 10:45:52 -07:00

170 lines
5.9 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
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 369ce9ff6c8bb97a64a8e229115564412e6e7654..e700875beb76dadd55b585aca748338def286908 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;
@@ -605,6 +604,17 @@ 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(int, int, int)
+ */
+ 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 85c9ea1241d580386be00fb85ea1446addd376c4..4f563c6afc3568a5a45594bcc87790eeefc4148d 100644
--- a/src/main/java/org/bukkit/World.java
+++ b/src/main/java/org/bukkit/World.java
@@ -90,6 +90,38 @@ public interface World extends PluginMessageRecipient, Metadatable, net.kyori.ad
@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)
+ */
+ @NotNull
+ 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
+ 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) coordinate 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 3ca05a6e86a5329cf452041eac476e3636eec34a..18ab5cca036522df2d245f755d6c67904e6398e8 100644
--- a/src/main/java/org/bukkit/block/Block.java
+++ b/src/main/java/org/bukkit/block/Block.java
@@ -155,6 +155,72 @@ public interface Block extends Metadatable {
*/
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
+ */
+ public default long getBlockKey() {
+ return Block.getBlockKey(this.getX(), this.getY(), this.getZ());
+ }
+
+ /**
+ * Returns the specified block coordinates packed into a long value
+ * <p>
+ * The return value can be computed as follows:
+ * <br>
+ * {@code long value = ((long)x & 0x7FFFFFF) | (((long)z & 0x7FFFFFF) << 27) | ((long)y << 54);}
+ * </p>
+ *
+ * <p>
+ * And may be unpacked as follows:
+ * <br>
+ * {@code int x = (int) ((packed << 37) >> 37);}
+ * <br>
+ * {@code int y = (int) (packed >>> 54);}
+ * <br>
+ * {@code int z = (int) ((packed << 10) >> 37);}
+ * </p>
+ *
+ * @return This block's x, y, and z coordinates packed into a long value
+ */
+ 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.
+ */
+ 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.
+ */
+ 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.
+ */
+ public static int getBlockKeyZ(long packed) {
+ return (int) ((packed << 10) >> 37);
+ }
+ // Paper End
+
/**
* Gets the Location of the block
*