diff options
Diffstat (limited to 'patches/api/0142-Async-Chunks-API.patch')
-rw-r--r-- | patches/api/0142-Async-Chunks-API.patch | 530 |
1 files changed, 530 insertions, 0 deletions
diff --git a/patches/api/0142-Async-Chunks-API.patch b/patches/api/0142-Async-Chunks-API.patch new file mode 100644 index 0000000000..68867e8a37 --- /dev/null +++ b/patches/api/0142-Async-Chunks-API.patch @@ -0,0 +1,530 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar <[email protected]> +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 b3098ce9134acf24f49d23fc1babe79c6bf502f1..5efe33cef4d9c153d760fc71606721ff8abafbfc 100644 +--- a/src/main/java/org/bukkit/World.java ++++ b/src/main/java/org/bukkit/World.java +@@ -950,6 +950,472 @@ public interface World extends RegionAccessor, WorldInfo, PluginMessageRecipient + } + // Paper end - additional getNearbyEntities API + ++ // Paper start - async chunks API ++ /** ++ * 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 - floor(world coordinate / 16) ++ * @param z Chunk Z-coordinate of the chunk - floor(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).exceptionally((ex) -> { ++ Bukkit.getLogger().log(java.util.logging.Level.WARNING, "Exception in chunk load callback", ex); ++ return null; ++ }); ++ } ++ ++ /** ++ * 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).exceptionally((ex) -> { ++ Bukkit.getLogger().log(java.util.logging.Level.WARNING, "Exception in chunk load callback", ex); ++ return null; ++ }); ++ } ++ ++ /** ++ * 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).exceptionally((ex) -> { ++ Bukkit.getLogger().log(java.util.logging.Level.WARNING, "Exception in chunk load callback", ex); ++ return null; ++ }); ++ } ++ ++ /** ++ * 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 - floor(world coordinate / 16) ++ * @param z Chunk Z-coordinate of the chunk - floor(world coordinate / 16) ++ * @param cb Callback to receive the chunk when it is loaded. ++ * will be executed synchronously ++ */ ++ default void getChunkAtAsync(final int x, final int z, final @NotNull Consumer<? super Chunk> cb) { ++ this.getChunkAtAsync(x, z, true).thenAccept(cb).exceptionally((ex) -> { ++ Bukkit.getLogger().log(java.util.logging.Level.WARNING, "Exception in chunk load callback", ex); ++ return null; ++ }); ++ } ++ ++ /** ++ * 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 - floor(world coordinate / 16) ++ * @param z Chunk Z-coordinate of the chunk - floor(world coordinate / 16) ++ * @param gen Should we generate a chunk if it doesn't exist or not ++ * @param cb Callback to receive the chunk when it is loaded. ++ * will be executed synchronously ++ */ ++ default void getChunkAtAsync(final int x, final int z, final boolean gen, final @NotNull Consumer<? super Chunk> cb) { ++ this.getChunkAtAsync(x, z, gen).thenAccept(cb).exceptionally((ex) -> { ++ Bukkit.getLogger().log(java.util.logging.Level.WARNING, "Exception in chunk load callback", ex); ++ return null; ++ }); ++ } ++ ++ /** ++ * 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 ++ */ ++ default void getChunkAtAsync(final @NotNull Location loc, final @NotNull Consumer<? super Chunk> cb) { ++ this.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 if it doesn't exist ++ * @param cb Callback to receive the chunk when it is loaded. ++ * will be executed synchronously ++ */ ++ default void getChunkAtAsync(final @NotNull Location loc, final boolean gen, final @NotNull Consumer<? super Chunk> cb) { ++ this.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 ++ */ ++ default void getChunkAtAsync(final @NotNull Block block, final @NotNull Consumer<? super Chunk> cb) { ++ this.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 if it doesn't exist ++ * @param cb Callback to receive the chunk when it is loaded. ++ * will be executed synchronously ++ */ ++ default void getChunkAtAsync(final @NotNull Block block, final boolean gen, final @NotNull Consumer<? super Chunk> cb) { ++ this.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 ++ */ ++ default @NotNull java.util.concurrent.CompletableFuture<Chunk> getChunkAtAsync(final @NotNull Location loc) { ++ return this.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 if it doesn't exist ++ * @return Future that will resolve when the chunk is loaded ++ */ ++ default @NotNull java.util.concurrent.CompletableFuture<Chunk> getChunkAtAsync(final @NotNull Location loc, final boolean gen) { ++ return this.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 ++ */ ++ default @NotNull java.util.concurrent.CompletableFuture<Chunk> getChunkAtAsync(final @NotNull Block block) { ++ return this.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 if it doesn't exist ++ * @return Future that will resolve when the chunk is loaded ++ */ ++ default @NotNull java.util.concurrent.CompletableFuture<Chunk> getChunkAtAsync(final @NotNull Block block, final boolean gen) { ++ return this.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 Chunk X-coordinate of the chunk - floor(world coordinate / 16) ++ * @param z Chunk Z-coordinate of the chunk - floor(world coordinate / 16) ++ * @return Future that will resolve when the chunk is loaded ++ */ ++ default @NotNull java.util.concurrent.CompletableFuture<Chunk> getChunkAtAsync(final int x, final int z) { ++ return this.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 - floor(world coordinate / 16) ++ * @param z Chunk Z-coordinate of the chunk - floor(world coordinate / 16) ++ * @param gen Should we generate a chunk if it doesn't exist or not ++ * @return Future that will resolve when the chunk is loaded ++ */ ++ default @NotNull java.util.concurrent.CompletableFuture<Chunk> getChunkAtAsync(final int x, final int z, final boolean gen) { ++ return this.getChunkAtAsync(x, z, gen, false); ++ } ++ ++ /** ++ * 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 ++ */ ++ default @NotNull java.util.concurrent.CompletableFuture<Chunk> getChunkAtAsyncUrgently(final @NotNull Location loc) { ++ return this.getChunkAtAsync((int) Math.floor(loc.getX()) >> 4, (int) Math.floor(loc.getZ()) >> 4, true, 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 if it doesn't exist ++ * @return Future that will resolve when the chunk is loaded ++ */ ++ default @NotNull java.util.concurrent.CompletableFuture<Chunk> getChunkAtAsyncUrgently(final @NotNull Location loc, final boolean gen) { ++ return this.getChunkAtAsync((int) Math.floor(loc.getX()) >> 4, (int) Math.floor(loc.getZ()) >> 4, gen, 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 ++ * @return Future that will resolve when the chunk is loaded ++ */ ++ default @NotNull java.util.concurrent.CompletableFuture<Chunk> getChunkAtAsyncUrgently(final @NotNull Block block) { ++ return this.getChunkAtAsync(block.getX() >> 4, block.getZ() >> 4, true, 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 if it doesn't exist ++ * @return Future that will resolve when the chunk is loaded ++ */ ++ default @NotNull java.util.concurrent.CompletableFuture<Chunk> getChunkAtAsyncUrgently(final @NotNull Block block, final boolean gen) { ++ return this.getChunkAtAsync(block.getX() >> 4, block.getZ() >> 4, gen, 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 X Coord ++ * @param z Z Coord ++ * @return Future that will resolve when the chunk is loaded ++ */ ++ default @NotNull java.util.concurrent.CompletableFuture<Chunk> getChunkAtAsyncUrgently(final int x, final int z) { ++ return this.getChunkAtAsync(x, z, true, true); ++ } ++ ++ java.util.concurrent.@NotNull CompletableFuture<Chunk> getChunkAtAsync(int x, int z, boolean gen, boolean urgent); ++ // Paper end - async chunks API ++ + /** + * Get a list of all players in this World + * +diff --git a/src/main/java/org/bukkit/entity/Entity.java b/src/main/java/org/bukkit/entity/Entity.java +index 1e43deadce5a1a0e97521b1f69fee3106f5a0b9e..f1fc42ad24648ee481b9a5d4c4cc58ae8c0a93c1 100644 +--- a/src/main/java/org/bukkit/entity/Entity.java ++++ b/src/main/java/org/bukkit/entity/Entity.java +@@ -168,6 +168,39 @@ 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 ++ */ ++ default java.util.concurrent.@NotNull CompletableFuture<Boolean> teleportAsync(final @NotNull Location loc) { ++ return this.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 ++ */ ++ default java.util.concurrent.@NotNull CompletableFuture<Boolean> teleportAsync(final @NotNull Location loc, final @NotNull TeleportCause cause) { ++ final class Holder { ++ static final io.papermc.paper.entity.TeleportFlag[] EMPTY_FLAGS = new io.papermc.paper.entity.TeleportFlag[0]; ++ } ++ return this.teleportAsync(loc, cause, Holder.EMPTY_FLAGS); ++ } ++ ++ /** ++ * 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 ++ * @param teleportFlags Flags to be used in this teleportation ++ * @return A future that will be completed with the result of the teleport ++ */ ++ java.util.concurrent.@NotNull CompletableFuture<Boolean> teleportAsync(@NotNull Location loc, @NotNull TeleportCause cause, @NotNull io.papermc.paper.entity.TeleportFlag @NotNull... teleportFlags); ++ // Paper end ++ + /** + * Returns a list of entities within a bounding box centered around this + * entity |