PaperMC/Spigot-API-Patches/0133-Async-Chunks-API.patch
Shane Freeder 7e8ae207bd
Updated Upstream (Bukkit/CraftBukkit/Spigot)
Upstream has released updates that appears to apply and compile correctly.
This update has not been tested by PaperMC and as with ANY update, please do your own testing

Bukkit Changes:
e99c9444 Add Plugin Chunk Ticket API
6a235f06 Fix incorrect nullability annotations for PlayerJoinEvent's join message

CraftBukkit Changes:
5f889388 Tweak build expiration to 7 days
572c02b0 MC-155077, SPIGOT-5113: EntityTracker desync
7ad3a1f4 SPIGOT-5146: BlockDataMeta does not work
60860983 SPIGOT-5155: Setting EntityExplodeEvent yield to 0 still causes blocks to drop
087a2cf4 Print number of force loaded chunks per plugin in crash reports
07b5b06d Add Plugin Chunk Ticket API
7ffb2a27 SPIGOT-5149: resetRecipes does nothing
a2275f19 SPIGOT-5141: World.generateTree() causes ClassCastException with huge mushrooms
31d4a777 SPIGOT-5142: Ignore invalid firework effects

Spigot Changes:
5e4e7f32 BUILDTOOLS-471: Rebuild patches
6e944739 SPIGOT-5159: Raider activation range overridden by Monster range
2019-07-11 17:59:21 +01:00

410 lines
18 KiB
Diff

From b8c066af3a770415b3ca9f8a8a16f19a6b1a6f8c Mon Sep 17 00:00:00 2001
From: Aikar <aikar@aikar.co>
Date: Mon, 29 Feb 2016 17:43:33 -0600
Subject: [PATCH] Async Chunks API
Adds API's to load or generate chunks asynchronously.
Also adds utility methods to Entity to teleport asynchronously.
diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java
index 189df011..d4fcbf60 100644
--- a/src/main/java/org/bukkit/World.java
+++ b/src/main/java/org/bukkit/World.java
@@ -172,6 +172,358 @@ public interface World extends PluginMessageRecipient, Metadatable {
public default Chunk getChunkAt(long chunkKey) {
return getChunkAt((int) chunkKey, (int) (chunkKey >> 32));
}
+
+ /**
+ * This is the Legacy API before Java 8 was supported. Java 8 Consumer is provided,
+ * as well as future support
+ *
+ * Used by {@link World#getChunkAtAsync(Location,ChunkLoadCallback)} methods
+ * to request a {@link Chunk} to be loaded, with this callback receiving
+ * the chunk when it is finished.
+ *
+ * This callback will be executed on synchronously on the main thread.
+ *
+ * Timing and order this callback is fired is intentionally not defined and
+ * and subject to change.
+ *
+ * @deprecated Use either the Future or the Consumer based methods
+ */
+ @Deprecated
+ public static interface ChunkLoadCallback extends java.util.function.Consumer<Chunk> {
+ public void onLoad(@NotNull Chunk chunk);
+
+ // backwards compat to old api
+ @Override
+ default void accept(@NotNull Chunk chunk) {
+ onLoad(chunk);
+ }
+ }
+
+ /**
+ * Requests a {@link Chunk} to be loaded at the given coordinates
+ *
+ * This method makes no guarantee on how fast the chunk will load,
+ * and will return the chunk to the callback at a later time.
+ *
+ * You should use this method if you need a chunk but do not need it
+ * immediately, and you wish to let the server control the speed
+ * of chunk loads, keeping performance in mind.
+ *
+ * The {@link ChunkLoadCallback} will always be executed synchronously
+ * on the main Server Thread.
+ *
+ * @deprecated Use either the Future or the Consumer based methods
+ * @param x Chunk X-coordinate of the chunk - (world coordinate / 16)
+ * @param z Chunk Z-coordinate of the chunk - (world coordinate / 16)
+ * @param cb Callback to receive the chunk when it is loaded.
+ * will be executed synchronously
+ */
+ @Deprecated
+ public default void getChunkAtAsync(int x, int z, @NotNull ChunkLoadCallback cb) {
+ getChunkAtAsync(x, z, true).thenAccept(cb::onLoad);
+ }
+
+ /**
+ * Requests a {@link Chunk} to be loaded at the given {@link Location}
+ *
+ * This method makes no guarantee on how fast the chunk will load,
+ * and will return the chunk to the callback at a later time.
+ *
+ * You should use this method if you need a chunk but do not need it
+ * immediately, and you wish to let the server control the speed
+ * of chunk loads, keeping performance in mind.
+ *
+ * The {@link ChunkLoadCallback} will always be executed synchronously
+ * on the main Server Thread.
+ *
+ * @deprecated Use either the Future or the Consumer based methods
+ * @param loc Location of the chunk
+ * @param cb Callback to receive the chunk when it is loaded.
+ * will be executed synchronously
+ */
+ @Deprecated
+ public default void getChunkAtAsync(@NotNull Location loc, @NotNull ChunkLoadCallback cb) {
+ getChunkAtAsync(loc, true).thenAccept(cb::onLoad);
+ }
+
+ /**
+ * Requests {@link Chunk} to be loaded that contains the given {@link Block}
+ *
+ * This method makes no guarantee on how fast the chunk will load,
+ * and will return the chunk to the callback at a later time.
+ *
+ * You should use this method if you need a chunk but do not need it
+ * immediately, and you wish to let the server control the speed
+ * of chunk loads, keeping performance in mind.
+ *
+ * The {@link ChunkLoadCallback} will always be executed synchronously
+ * on the main Server Thread.
+ *
+ * @deprecated Use either the Future or the Consumer based methods
+ * @param block Block to get the containing chunk from
+ * @param cb Callback to receive the chunk when it is loaded.
+ * will be executed synchronously
+ */
+ @Deprecated
+ public default void getChunkAtAsync(@NotNull Block block, @NotNull ChunkLoadCallback cb) {
+ getChunkAtAsync(block, true).thenAccept(cb::onLoad);
+ }
+
+ /**
+ * Requests a {@link Chunk} to be loaded at the given coordinates
+ *
+ * This method makes no guarantee on how fast the chunk will load,
+ * and will return the chunk to the callback at a later time.
+ *
+ * You should use this method if you need a chunk but do not need it
+ * immediately, and you wish to let the server control the speed
+ * of chunk loads, keeping performance in mind.
+ *
+ * The {@link java.util.function.Consumer} will always be executed synchronously
+ * on the main Server Thread.
+ *
+ * @param x Chunk X-coordinate of the chunk - (world coordinate / 16)
+ * @param z Chunk Z-coordinate of the chunk - (world coordinate / 16)
+ * @param cb Callback to receive the chunk when it is loaded.
+ * will be executed synchronously
+ */
+ public default void getChunkAtAsync(int x, int z, @NotNull java.util.function.Consumer<Chunk> cb) {
+ getChunkAtAsync(x, z, true).thenAccept(cb);
+ }
+
+ /**
+ * Requests a {@link Chunk} to be loaded at the given coordinates
+ *
+ * This method makes no guarantee on how fast the chunk will load,
+ * and will return the chunk to the callback at a later time.
+ *
+ * You should use this method if you need a chunk but do not need it
+ * immediately, and you wish to let the server control the speed
+ * of chunk loads, keeping performance in mind.
+ *
+ * The {@link java.util.function.Consumer} will always be executed synchronously
+ * on the main Server Thread.
+ *
+ * @param x Chunk X-coordinate of the chunk - (world coordinate / 16)
+ * @param z Chunk Z-coordinate of the chunk - (world coordinate / 16)
+ * @param gen Should we generate a chunk if it doesn't exists or not
+ * @param cb Callback to receive the chunk when it is loaded.
+ * will be executed synchronously
+ */
+ public default void getChunkAtAsync(int x, int z, boolean gen, @NotNull java.util.function.Consumer<Chunk> cb) {
+ getChunkAtAsync(x, z, gen).thenAccept(cb);
+ }
+
+ /**
+ * Requests a {@link Chunk} to be loaded at the given {@link Location}
+ *
+ * This method makes no guarantee on how fast the chunk will load,
+ * and will return the chunk to the callback at a later time.
+ *
+ * You should use this method if you need a chunk but do not need it
+ * immediately, and you wish to let the server control the speed
+ * of chunk loads, keeping performance in mind.
+ *
+ * The {@link java.util.function.Consumer} will always be executed synchronously
+ * on the main Server Thread.
+ *
+ * @param loc Location of the chunk
+ * @param cb Callback to receive the chunk when it is loaded.
+ * will be executed synchronously
+ */
+ public default void getChunkAtAsync(@NotNull Location loc, @NotNull java.util.function.Consumer<Chunk> cb) {
+ getChunkAtAsync((int)Math.floor(loc.getX()) >> 4, (int)Math.floor(loc.getZ()) >> 4, true, cb);
+ }
+
+ /**
+ * Requests a {@link Chunk} to be loaded at the given {@link Location}
+ *
+ * This method makes no guarantee on how fast the chunk will load,
+ * and will return the chunk to the callback at a later time.
+ *
+ * You should use this method if you need a chunk but do not need it
+ * immediately, and you wish to let the server control the speed
+ * of chunk loads, keeping performance in mind.
+ *
+ * The {@link java.util.function.Consumer} will always be executed synchronously
+ * on the main Server Thread.
+ *
+ * @param loc Location of the chunk
+ * @param gen Should the chunk generate
+ * @param cb Callback to receive the chunk when it is loaded.
+ * will be executed synchronously
+ */
+ public default void getChunkAtAsync(@NotNull Location loc, boolean gen, @NotNull java.util.function.Consumer<Chunk> cb) {
+ getChunkAtAsync((int)Math.floor(loc.getX()) >> 4, (int)Math.floor(loc.getZ()) >> 4, gen, cb);
+ }
+
+ /**
+ * Requests {@link Chunk} to be loaded that contains the given {@link Block}
+ *
+ * This method makes no guarantee on how fast the chunk will load,
+ * and will return the chunk to the callback at a later time.
+ *
+ * You should use this method if you need a chunk but do not need it
+ * immediately, and you wish to let the server control the speed
+ * of chunk loads, keeping performance in mind.
+ *
+ * The {@link java.util.function.Consumer} will always be executed synchronously
+ * on the main Server Thread.
+ *
+ * @param block Block to get the containing chunk from
+ * @param cb Callback to receive the chunk when it is loaded.
+ * will be executed synchronously
+ */
+ public default void getChunkAtAsync(@NotNull Block block, @NotNull java.util.function.Consumer<Chunk> cb) {
+ getChunkAtAsync(block.getX() >> 4, block.getZ() >> 4, true, cb);
+ }
+
+ /**
+ * Requests {@link Chunk} to be loaded that contains the given {@link Block}
+ *
+ * This method makes no guarantee on how fast the chunk will load,
+ * and will return the chunk to the callback at a later time.
+ *
+ * You should use this method if you need a chunk but do not need it
+ * immediately, and you wish to let the server control the speed
+ * of chunk loads, keeping performance in mind.
+ *
+ * The {@link java.util.function.Consumer} will always be executed synchronously
+ * on the main Server Thread.
+ *
+ * @param block Block to get the containing chunk from
+ * @param gen Should the chunk generate
+ * @param cb Callback to receive the chunk when it is loaded.
+ * will be executed synchronously
+ */
+ public default void getChunkAtAsync(@NotNull Block block, boolean gen, @NotNull java.util.function.Consumer<Chunk> cb) {
+ getChunkAtAsync(block.getX() >> 4, block.getZ() >> 4, gen, cb);
+ }
+
+ /**
+ * Requests a {@link Chunk} to be loaded at the given coordinates
+ *
+ * This method makes no guarantee on how fast the chunk will load,
+ * and will return the chunk to the callback at a later time.
+ *
+ * You should use this method if you need a chunk but do not need it
+ * immediately, and you wish to let the server control the speed
+ * of chunk loads, keeping performance in mind.
+ *
+ * The future will always be executed synchronously
+ * on the main Server Thread.
+ * @param loc Location to load the corresponding chunk from
+ * @return Future that will resolve when the chunk is loaded
+ */
+ @NotNull
+ public default java.util.concurrent.CompletableFuture<Chunk> getChunkAtAsync(@NotNull Location loc) {
+ return getChunkAtAsync((int)Math.floor(loc.getX()) >> 4, (int)Math.floor(loc.getZ()) >> 4, true);
+ }
+
+ /**
+ * Requests a {@link Chunk} to be loaded at the given coordinates
+ *
+ * This method makes no guarantee on how fast the chunk will load,
+ * and will return the chunk to the callback at a later time.
+ *
+ * You should use this method if you need a chunk but do not need it
+ * immediately, and you wish to let the server control the speed
+ * of chunk loads, keeping performance in mind.
+ *
+ * The future will always be executed synchronously
+ * on the main Server Thread.
+ * @param loc Location to load the corresponding chunk from
+ * @param gen Should the chunk generate
+ * @return Future that will resolve when the chunk is loaded
+ */
+ @NotNull
+ public default java.util.concurrent.CompletableFuture<Chunk> getChunkAtAsync(@NotNull Location loc, boolean gen) {
+ return getChunkAtAsync((int)Math.floor(loc.getX()) >> 4, (int)Math.floor(loc.getZ()) >> 4, gen);
+ }
+
+ /**
+ * Requests a {@link Chunk} to be loaded at the given coordinates
+ *
+ * This method makes no guarantee on how fast the chunk will load,
+ * and will return the chunk to the callback at a later time.
+ *
+ * You should use this method if you need a chunk but do not need it
+ * immediately, and you wish to let the server control the speed
+ * of chunk loads, keeping performance in mind.
+ *
+ * The future will always be executed synchronously
+ * on the main Server Thread.
+ * @param block Block to load the corresponding chunk from
+ * @return Future that will resolve when the chunk is loaded
+ */
+ @NotNull
+ public default java.util.concurrent.CompletableFuture<Chunk> getChunkAtAsync(@NotNull Block block) {
+ return getChunkAtAsync(block.getX() >> 4, block.getZ() >> 4, true);
+ }
+
+ /**
+ * Requests a {@link Chunk} to be loaded at the given coordinates
+ *
+ * This method makes no guarantee on how fast the chunk will load,
+ * and will return the chunk to the callback at a later time.
+ *
+ * You should use this method if you need a chunk but do not need it
+ * immediately, and you wish to let the server control the speed
+ * of chunk loads, keeping performance in mind.
+ *
+ * The future will always be executed synchronously
+ * on the main Server Thread.
+ * @param block Block to load the corresponding chunk from
+ * @param gen Should the chunk generate
+ * @return Future that will resolve when the chunk is loaded
+ */
+ @NotNull
+ public default java.util.concurrent.CompletableFuture<Chunk> getChunkAtAsync(@NotNull Block block, boolean gen) {
+ return getChunkAtAsync(block.getX() >> 4, block.getZ() >> 4, gen);
+ }
+
+ /**
+ * Requests a {@link Chunk} to be loaded at the given coordinates
+ *
+ * This method makes no guarantee on how fast the chunk will load,
+ * and will return the chunk to the callback at a later time.
+ *
+ * You should use this method if you need a chunk but do not need it
+ * immediately, and you wish to let the server control the speed
+ * of chunk loads, keeping performance in mind.
+ *
+ * The future will always be executed synchronously
+ * on the main Server Thread.
+ *
+ * @param x X Coord
+ * @param z Z Coord
+ * @return Future that will resolve when the chunk is loaded
+ */
+ @NotNull
+ public default java.util.concurrent.CompletableFuture<Chunk> getChunkAtAsync(int x, int z) {
+ return getChunkAtAsync(x, z, true);
+ }
+
+ /**
+ * Requests a {@link Chunk} to be loaded at the given coordinates
+ *
+ * This method makes no guarantee on how fast the chunk will load,
+ * and will return the chunk to the callback at a later time.
+ *
+ * You should use this method if you need a chunk but do not need it
+ * immediately, and you wish to let the server control the speed
+ * of chunk loads, keeping performance in mind.
+ *
+ * The future will always be executed synchronously
+ * on the main Server Thread.
+ *
+ * @param x Chunk X-coordinate of the chunk - (world coordinate / 16)
+ * @param z Chunk Z-coordinate of the chunk - (world coordinate / 16)
+ * @param gen Should we generate a chunk if it doesn't exists or not
+ * @return Future that will resolve when the chunk is loaded
+ */
+ @NotNull
+ public java.util.concurrent.CompletableFuture<Chunk> getChunkAtAsync(int x, int z, boolean gen);
// Paper end
/**
diff --git a/src/main/java/org/bukkit/entity/Entity.java b/src/main/java/org/bukkit/entity/Entity.java
index 2d3cee14..f41243f9 100644
--- a/src/main/java/org/bukkit/entity/Entity.java
+++ b/src/main/java/org/bukkit/entity/Entity.java
@@ -157,6 +157,30 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent
*/
public boolean teleport(@NotNull Entity destination, @NotNull TeleportCause cause);
+ // Paper start
+ /**
+ * Loads/Generates(in 1.13+) the Chunk asynchronously, and then teleports the entity when the chunk is ready.
+ * @param loc Location to teleport to
+ * @return A future that will be completed with the result of the teleport
+ */
+ @NotNull
+ public default java.util.concurrent.CompletableFuture<Boolean> teleportAsync(@NotNull Location loc) {
+ return teleportAsync(loc, TeleportCause.PLUGIN);
+ }
+ /**
+ * Loads/Generates(in 1.13+) the Chunk asynchronously, and then teleports the entity when the chunk is ready.
+ * @param loc Location to teleport to
+ * @param cause Reason for teleport
+ * @return A future that will be completed with the result of the teleport
+ */
+ @NotNull
+ public default java.util.concurrent.CompletableFuture<Boolean> teleportAsync(@NotNull Location loc, @NotNull TeleportCause cause) {
+ java.util.concurrent.CompletableFuture<Boolean> future = new java.util.concurrent.CompletableFuture<>();
+ loc.getWorld().getChunkAtAsync(loc).thenAccept((chunk) -> future.complete(teleport(loc, cause)));
+ return future;
+ }
+ // Paper end
+
/**
* Returns a list of entities within a bounding box centered around this
* entity
--
2.22.0