From 68b20e0acc3257956ad11a2e9b8390c66b2a9e4f Mon Sep 17 00:00:00 2001 From: Spottedleaf Date: Tue, 7 Mar 2023 14:41:00 -0800 Subject: [PATCH] Add API for checking ownership of region by position/entity This may be useful for plugins which want to perform operations over large areas outside of the buffer zone provided by the regionaliser, as it is not guaranteed that anything outside of the buffer zone is owned. Then, the plugins may use the schedulers depending on the result of the ownership check. --- ...king-ownership-of-region-by-position.patch | 205 ++++++++++++++++++ patches/server/0004-Threaded-Regions.patch | 64 +++++- regiontodo.txt | 1 - 3 files changed, 264 insertions(+), 6 deletions(-) create mode 100644 patches/api/0005-Add-API-for-checking-ownership-of-region-by-position.patch diff --git a/patches/api/0005-Add-API-for-checking-ownership-of-region-by-position.patch b/patches/api/0005-Add-API-for-checking-ownership-of-region-by-position.patch new file mode 100644 index 0000000..68407b6 --- /dev/null +++ b/patches/api/0005-Add-API-for-checking-ownership-of-region-by-position.patch @@ -0,0 +1,205 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Tue, 7 Mar 2023 14:34:09 -0800 +Subject: [PATCH] Add API for checking ownership of region by position/entity + +This may be useful for plugins which want to perform operations +over large areas outside of the buffer zone provided by the +regionaliser, as it is not guaranteed that anything outside +of the buffer zone is owned. Then, the plugins may use +the schedulers depending on the result of the ownership +check. + +diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java +index 3b8a6d7336b0cb20594de9c6b56f215f1370ce89..aee6508cec0631fc7b5fe6bf1b978a5c01437422 100644 +--- a/src/main/java/org/bukkit/Bukkit.java ++++ b/src/main/java/org/bukkit/Bukkit.java +@@ -2474,6 +2474,100 @@ public final class Bukkit { + public static @NotNull io.papermc.paper.threadedregions.scheduler.RegionisedScheduler getRegionScheduler() { + return server.getRegionScheduler(); + } ++ ++ /** ++ * Returns whether the current thread is ticking a region and that the region being ticked ++ * owns the chunk at the specified world and block position. ++ * @param world Specified world. ++ * @param position Specified block position. ++ */ ++ public static boolean isOwnedByCurrentRegion(@NotNull World world, @NotNull org.bukkit.util.Vector position) { ++ return server.isOwnedByCurrentRegion(world, position); ++ } ++ ++ /** ++ * Returns whether the current thread is ticking a region and that the region being ticked ++ * owns the chunks centered at the specified block position within the specified square radius. ++ * Specifically, this function checks that every chunk with position x in [centerX - radius, centerX + radius] and ++ * position z in [centerZ - radius, centerZ + radius] is owned by the current ticking region. ++ * @param world Specified world. ++ * @param position Specified block position. ++ * @param squareRadiusChunks Specified square radius. Must be >= 0. Note that this parameter is not a squared ++ * radius, but rather a Chebyshev Distance. ++ */ ++ public static boolean isOwnedByCurrentRegion(@NotNull World world, @NotNull org.bukkit.util.Vector position, int squareRadiusChunks) { ++ return server.isOwnedByCurrentRegion(world, position, squareRadiusChunks); ++ } ++ ++ /** ++ * Returns whether the current thread is ticking a region and that the region being ticked ++ * owns the chunk at the specified world and block position as included in the specified location. ++ * @param location Specified location, must have a non-null world. ++ */ ++ public static boolean isOwnedByCurrentRegion(@NotNull Location location) { ++ return server.isOwnedByCurrentRegion(location); ++ } ++ ++ /** ++ * Returns whether the current thread is ticking a region and that the region being ticked ++ * owns the chunks centered at the specified world and block position as included in the specified location ++ * within the specified square radius. ++ * Specifically, this function checks that every chunk with position x in [centerX - radius, centerX + radius] and ++ * position z in [centerZ - radius, centerZ + radius] is owned by the current ticking region. ++ * @param location Specified location, must have a non-null world. ++ * @param squareRadiusChunks Specified square radius. Must be >= 0. Note that this parameter is not a squared ++ * radius, but rather a Chebyshev Distance. ++ */ ++ public static boolean isOwnedByCurrentRegion(@NotNull Location location, int squareRadiusChunks) { ++ return server.isOwnedByCurrentRegion(location, squareRadiusChunks); ++ } ++ ++ /** ++ * Returns whether the current thread is ticking a region and that the region being ticked ++ * owns the chunk at the specified block position. ++ * @param block Specified block position. ++ */ ++ public static boolean isOwnedByCurrentRegion(@NotNull org.bukkit.block.Block block) { ++ return server.isOwnedByCurrentRegion(block); ++ } ++ ++ /** ++ * Returns whether the current thread is ticking a region and that the region being ticked ++ * owns the chunk at the specified world and chunk position. ++ * @param world Specified world. ++ * @param chunkX Specified x-coordinate of the chunk position. ++ * @param chunkZ Specified z-coordinate of the chunk position. ++ */ ++ public static boolean isOwnedByCurrentRegion(@NotNull World world, int chunkX, int chunkZ) { ++ return server.isOwnedByCurrentRegion(world, chunkX, chunkZ); ++ } ++ ++ /** ++ * Returns whether the current thread is ticking a region and that the region being ticked ++ * owns the chunks centered at the specified world and chunk position within the specified ++ * square radius. ++ * Specifically, this function checks that every chunk with position x in [centerX - radius, centerX + radius] and ++ * position z in [centerZ - radius, centerZ + radius] is owned by the current ticking region. ++ * @param world Specified world. ++ * @param chunkX Specified x-coordinate of the chunk position. ++ * @param chunkZ Specified z-coordinate of the chunk position. ++ * @param squareRadiusChunks Specified square radius. Must be >= 0. Note that this parameter is not a squared ++ * radius, but rather a Chebyshev Distance. ++ */ ++ public static boolean isOwnedByCurrentRegion(@NotNull World world, int chunkX, int chunkZ, int squareRadiusChunks) { ++ return server.isOwnedByCurrentRegion(world, chunkX, chunkZ, squareRadiusChunks); ++ } ++ ++ /** ++ * Returns whether the current thread is ticking a region and that the region being ticked ++ * owns the specified entity. Note that this function is the only appropriate method of checking ++ * for ownership of an entity, as retrieving the entity's location is undefined unless the entity is owned ++ * by the current region. ++ * @param entity Specified entity. ++ */ ++ public static boolean isOwnedByCurrentRegion(@NotNull Entity entity) { ++ return server.isOwnedByCurrentRegion(entity); ++ } + // Folia end - region threading API + + @NotNull +diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java +index 135467092eec33a21b171df39267d15bad26003e..48902e9aec6af7a4252db5b567d08a80f5709cbf 100644 +--- a/src/main/java/org/bukkit/Server.java ++++ b/src/main/java/org/bukkit/Server.java +@@ -2152,5 +2152,83 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi + * @return the region task scheduler + */ + @NotNull io.papermc.paper.threadedregions.scheduler.RegionisedScheduler getRegionScheduler(); ++ ++ /** ++ * Returns whether the current thread is ticking a region and that the region being ticked ++ * owns the chunk at the specified world and block position. ++ * @param world Specified world. ++ * @param position Specified block position. ++ */ ++ public boolean isOwnedByCurrentRegion(@NotNull World world, @NotNull org.bukkit.util.Vector position); ++ ++ /** ++ * Returns whether the current thread is ticking a region and that the region being ticked ++ * owns the chunks centered at the specified block position within the specified square radius. ++ * Specifically, this function checks that every chunk with position x in [centerX - radius, centerX + radius] and ++ * position z in [centerZ - radius, centerZ + radius] is owned by the current ticking region. ++ * @param world Specified world. ++ * @param position Specified block position. ++ * @param squareRadiusChunks Specified square radius. Must be >= 0. Note that this parameter is not a squared ++ * radius, but rather a Chebyshev Distance. ++ */ ++ public boolean isOwnedByCurrentRegion(@NotNull World world, @NotNull org.bukkit.util.Vector position, int squareRadiusChunks); ++ ++ /** ++ * Returns whether the current thread is ticking a region and that the region being ticked ++ * owns the chunk at the specified world and block position as included in the specified location. ++ * @param location Specified location, must have a non-null world. ++ */ ++ public boolean isOwnedByCurrentRegion(@NotNull Location location); ++ ++ /** ++ * Returns whether the current thread is ticking a region and that the region being ticked ++ * owns the chunks centered at the specified world and block position as included in the specified location ++ * within the specified square radius. ++ * Specifically, this function checks that every chunk with position x in [centerX - radius, centerX + radius] and ++ * position z in [centerZ - radius, centerZ + radius] is owned by the current ticking region. ++ * @param location Specified location, must have a non-null world. ++ * @param squareRadiusChunks Specified square radius. Must be >= 0. Note that this parameter is not a squared ++ * radius, but rather a Chebyshev Distance. ++ */ ++ public boolean isOwnedByCurrentRegion(@NotNull Location location, int squareRadiusChunks); ++ ++ /** ++ * Returns whether the current thread is ticking a region and that the region being ticked ++ * owns the chunk at the specified block position. ++ * @param block Specified block position. ++ */ ++ public boolean isOwnedByCurrentRegion(@NotNull org.bukkit.block.Block block); ++ ++ /** ++ * Returns whether the current thread is ticking a region and that the region being ticked ++ * owns the chunk at the specified world and chunk position. ++ * @param world Specified world. ++ * @param chunkX Specified x-coordinate of the chunk position. ++ * @param chunkZ Specified z-coordinate of the chunk position. ++ */ ++ public boolean isOwnedByCurrentRegion(@NotNull World world, int chunkX, int chunkZ); ++ ++ /** ++ * Returns whether the current thread is ticking a region and that the region being ticked ++ * owns the chunks centered at the specified world and chunk position within the specified ++ * square radius. ++ * Specifically, this function checks that every chunk with position x in [centerX - radius, centerX + radius] and ++ * position z in [centerZ - radius, centerZ + radius] is owned by the current ticking region. ++ * @param world Specified world. ++ * @param chunkX Specified x-coordinate of the chunk position. ++ * @param chunkZ Specified z-coordinate of the chunk position. ++ * @param squareRadiusChunks Specified square radius. Must be >= 0. Note that this parameter is not a squared ++ * radius, but rather a Chebyshev Distance. ++ */ ++ public boolean isOwnedByCurrentRegion(@NotNull World world, int chunkX, int chunkZ, int squareRadiusChunks); ++ ++ /** ++ * Returns whether the current thread is ticking a region and that the region being ticked ++ * owns the specified entity. Note that this function is the only appropriate method of checking ++ * for ownership of an entity, as retrieving the entity's location is undefined unless the entity is owned ++ * by the current region. ++ * @param entity Specified entity. ++ */ ++ public boolean isOwnedByCurrentRegion(@NotNull Entity entity); + // Folia end - region threading API + } diff --git a/patches/server/0004-Threaded-Regions.patch b/patches/server/0004-Threaded-Regions.patch index cb325bc..9c4ddb6 100644 --- a/patches/server/0004-Threaded-Regions.patch +++ b/patches/server/0004-Threaded-Regions.patch @@ -21802,10 +21802,10 @@ index 7f1ac2cb29eb84833c0895442d611dfa0504527e..c79cfebc65fd04994735dabcf5bb6e6c LevelChunkTicks levelChunkTicks = this.allContainers.get(l); if (levelChunkTicks == null) { diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 2ea3778ee1348e5d06b15a2c5dc5d9bd4136dbe3..72a8e27c5ff6063d2e2b3590390b24a112387535 100644 +index 2ea3778ee1348e5d06b15a2c5dc5d9bd4136dbe3..4c09a5a6a3f27c8e989cd35d70e999131a65b9d5 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -307,6 +307,15 @@ public final class CraftServer implements Server { +@@ -307,6 +307,69 @@ public final class CraftServer implements Server { CraftItemFactory.instance(); } @@ -21816,12 +21816,66 @@ index 2ea3778ee1348e5d06b15a2c5dc5d9bd4136dbe3..72a8e27c5ff6063d2e2b3590390b24a1 + public final io.papermc.paper.threadedregions.scheduler.RegionisedScheduler getRegionScheduler() { + return this.regionisedScheduler; + } ++ ++ @Override ++ public final boolean isOwnedByCurrentRegion(World world, org.bukkit.util.Vector position) { ++ return io.papermc.paper.util.TickThread.isTickThreadFor( ++ ((CraftWorld)world).getHandle(), position.getBlockX() >> 4, position.getBlockZ() >> 4 ++ ); ++ } ++ ++ @Override ++ public final boolean isOwnedByCurrentRegion(World world, org.bukkit.util.Vector position, int squareRadiusChunks) { ++ return io.papermc.paper.util.TickThread.isTickThreadFor( ++ ((CraftWorld)world).getHandle(), position.getBlockX() >> 4, position.getBlockZ() >> 4, squareRadiusChunks ++ ); ++ } ++ ++ @Override ++ public final boolean isOwnedByCurrentRegion(Location location) { ++ World world = location.getWorld(); ++ return io.papermc.paper.util.TickThread.isTickThreadFor( ++ ((CraftWorld)world).getHandle(), location.getBlockX() >> 4, location.getBlockZ() >> 4 ++ ); ++ } ++ ++ @Override ++ public final boolean isOwnedByCurrentRegion(Location location, int squareRadiusChunks) { ++ World world = location.getWorld(); ++ return io.papermc.paper.util.TickThread.isTickThreadFor( ++ ((CraftWorld)world).getHandle(), location.getBlockX() >> 4, location.getBlockZ() >> 4, squareRadiusChunks ++ ); ++ } ++ ++ @Override ++ public final boolean isOwnedByCurrentRegion(org.bukkit.block.Block block) { ++ return this.isOwnedByCurrentRegion(block.getLocation()); ++ } ++ ++ @Override ++ public final boolean isOwnedByCurrentRegion(World world, int chunkX, int chunkZ) { ++ return io.papermc.paper.util.TickThread.isTickThreadFor( ++ ((CraftWorld)world).getHandle(), chunkX, chunkZ ++ ); ++ } ++ ++ @Override ++ public final boolean isOwnedByCurrentRegion(World world, int chunkX, int chunkZ, int squareRadiusChunks) {] ++ return io.papermc.paper.util.TickThread.isTickThreadFor( ++ ((CraftWorld)world).getHandle(), chunkX, chunkZ, squareRadiusChunks ++ ); ++ } ++ ++ @Override ++ public final boolean isOwnedByCurrentRegion(Entity entity) { ++ return io.papermc.paper.util.TickThread.isTickThreadFor(((org.bukkit.craftbukkit.entity.CraftEntity)entity).getHandle()); ++ } + // Folia end - region threading API + public CraftServer(DedicatedServer console, PlayerList playerList) { this.console = console; this.playerList = (DedicatedPlayerList) playerList; -@@ -879,6 +888,9 @@ public final class CraftServer implements Server { +@@ -879,6 +942,9 @@ public final class CraftServer implements Server { // NOTE: Should only be called from DedicatedServer.ah() public boolean dispatchServerCommand(CommandSender sender, ConsoleInput serverCommand) { @@ -21831,7 +21885,7 @@ index 2ea3778ee1348e5d06b15a2c5dc5d9bd4136dbe3..72a8e27c5ff6063d2e2b3590390b24a1 if (sender instanceof Conversable) { Conversable conversable = (Conversable) sender; -@@ -898,12 +910,44 @@ public final class CraftServer implements Server { +@@ -898,12 +964,44 @@ public final class CraftServer implements Server { } } @@ -21876,7 +21930,7 @@ index 2ea3778ee1348e5d06b15a2c5dc5d9bd4136dbe3..72a8e27c5ff6063d2e2b3590390b24a1 // Paper Start if (!org.spigotmc.AsyncCatcher.shuttingDown && !Bukkit.isPrimaryThread()) { final CommandSender fSender = sender; -@@ -2913,7 +2957,7 @@ public final class CraftServer implements Server { +@@ -2913,7 +3011,7 @@ public final class CraftServer implements Server { @Override public int getCurrentTick() { diff --git a/regiontodo.txt b/regiontodo.txt index ca48e88..f5b7579 100644 --- a/regiontodo.txt +++ b/regiontodo.txt @@ -1,7 +1,6 @@ Get done before testing: - Mob#getTarget? - regioniser->regionaliser -- make plugin add ticket mt-safe Pre-Test: List of things not fully tested - Task queue