Skip to content

Commit

Permalink
Async structure locate API (#220)
Browse files Browse the repository at this point in the history
* Async structure locate api

* Mark as experimental
  • Loading branch information
HaHaWTH authored Feb 9, 2025
1 parent c4b9d82 commit a8ec234
Show file tree
Hide file tree
Showing 2 changed files with 135 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: HaHaWTH <[email protected]>
Date: Mon, 1 Nov 2077 00:00:00 +0800
Subject: [PATCH] Async structure locate api

This patch depends on Asynchronous locator patch.

Added some asynchronous structure locate methods in World,
requires async-locator to be enabled in Leaf config, or else it will fall back to sync methods.

diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java
index 3af8eb8064aeafa3606fed23e7ca2bc74c194726..2d314d7f75f320384c20c97f60c0c9611b890316 100644
--- a/src/main/java/org/bukkit/World.java
+++ b/src/main/java/org/bukkit/World.java
@@ -4047,6 +4047,60 @@ public interface World extends RegionAccessor, WorldInfo, PluginMessageRecipient
@Nullable
StructureSearchResult locateNearestStructure(@NotNull Location origin, @NotNull Structure structure, int radius, boolean findUnexplored);

+ // Leaf start - Async structure locate api
+ /**
+ * Find the closest nearby structure of a given {@link StructureType} asynchronously.
+ * <p>
+ * The {@code radius} is not a rigid square radius. Each structure may alter
+ * how many chunks to check for each iteration. Do not assume that only a
+ * radius x radius chunk area will be checked. For example,
+ * {@link StructureType#WOODLAND_MANSION} can potentially check up to 20,000
+ * blocks away (or more) regardless of the radius used.
+ * <p>
+ * This will <i>not</i> load or generate chunks.
+ * <p>
+ * The difference between searching for a {@link StructureType} and a
+ * {@link Structure} is, that a {@link StructureType} can refer to multiple
+ * {@link Structure Structures} while searching for a {@link Structure}
+ * while only search for the given {@link Structure}.
+ *
+ * @param origin where to start looking for a structure
+ * @param structureType the type of structure to find
+ * @param radius the radius, in chunks, around which to search
+ * @param findUnexplored true to only find unexplored structures
+ * @param afterComplete the action to perform once the search is complete.
+ * @see #locateNearestStructureAsync(Location, Structure, int, boolean, Consumer)
+ */
+ @org.jetbrains.annotations.ApiStatus.Experimental
+ void locateNearestStructureAsync(@NotNull Location origin, @NotNull StructureType structureType, int radius, boolean findUnexplored, @NotNull Consumer<@Nullable StructureSearchResult> afterComplete);
+
+ /**
+ * Find the closest nearby structure of a given {@link Structure} asynchronously.
+ * <p>
+ * The {@code radius} is not a rigid square radius. Each structure may alter
+ * how many chunks to check for each iteration. Do not assume that only a
+ * radius x radius chunk area will be checked. For example,
+ * {@link Structure#MANSION} can potentially check up to 20,000 blocks away
+ * (or more) regardless of the radius used.
+ * <p>
+ * This will <i>not</i> load or generate chunks.
+ * <p>
+ * The difference between searching for a {@link StructureType} and a
+ * {@link Structure} is, that a {@link StructureType} can refer to multiple
+ * {@link Structure Structures} while searching for a {@link Structure}
+ * while only search for the given {@link Structure}.
+ *
+ * @param origin where to start looking for a structure
+ * @param structure the structure to find
+ * @param radius the radius, in chunks, around which to search
+ * @param findUnexplored true to only find unexplored structures
+ * @param afterComplete the action to perform on server thread once the search is complete.
+ * @see #locateNearestStructureAsync(Location, StructureType, int, boolean, Consumer)
+ */
+ @org.jetbrains.annotations.ApiStatus.Experimental
+ void locateNearestStructureAsync(@NotNull Location origin, @NotNull Structure structure, int radius, boolean findUnexplored, @NotNull Consumer<@Nullable StructureSearchResult> afterComplete);
+ // Leaf end - Async structure locate api
+
// Paper start
/**
* Locates the nearest biome based on an origin, biome type, and radius to search.
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: HaHaWTH <[email protected]>
Date: Mon, 1 Nov 2077 00:00:00 +0800
Subject: [PATCH] Async structure locate api

This patch depends on Asynchronous locator patch.

Added some asynchronous structure locate methods in World,
requires async-locator to be enabled in Leaf config, or else it will fall back to sync methods.

diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
index ba5797e9e518d7a1054bad0c7a1fb10b9eaf32bd..5d3c7a131c6becbf0c95e5c7bd8b4e727a102b24 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
@@ -2298,6 +2298,45 @@ public class CraftWorld extends CraftRegionAccessor implements World {
return new CraftStructureSearchResult(CraftStructure.minecraftToBukkit(found.getSecond().value()), CraftLocation.toBukkit(found.getFirst(), this));
}

+ // Leaf start - Async structure locate api
+ @Override
+ public void locateNearestStructureAsync(Location origin, StructureType structureType, int radius, boolean findUnexplored, Consumer<StructureSearchResult> afterComplete) {
+ List<Structure> structures = new ArrayList<>();
+ for (Structure structure : RegistryAccess.registryAccess().getRegistry(RegistryKey.STRUCTURE)) {
+ if (structure.getStructureType() == structureType) {
+ structures.add(structure);
+ }
+ }
+
+ this.locateNearestStructureAsync(origin, structures, radius, findUnexplored, afterComplete);
+ }
+
+ @Override
+ public void locateNearestStructureAsync(Location origin, Structure structure, int radius, boolean findUnexplored, Consumer<StructureSearchResult> afterComplete) {
+ this.locateNearestStructureAsync(origin, List.of(structure), radius, findUnexplored, afterComplete);
+ }
+
+ public void locateNearestStructureAsync(Location origin, List<Structure> structures, int radius, boolean findUnexplored, Consumer<@Nullable StructureSearchResult> afterComplete) {
+ if (!org.dreeam.leaf.config.modules.async.AsyncLocator.enabled) afterComplete.accept(locateNearestStructure(origin, structures, radius, findUnexplored));
+ BlockPos originPos = BlockPos.containing(origin.getX(), origin.getY(), origin.getZ());
+ List<Holder<net.minecraft.world.level.levelgen.structure.Structure>> holders = new ArrayList<>();
+
+ for (Structure structure : structures) {
+ holders.add(Holder.direct(CraftStructure.bukkitToMinecraft(structure)));
+ }
+
+ org.dreeam.leaf.async.locate.AsyncLocator.locate(
+ this.getHandle(), HolderSet.direct(holders), originPos, radius, findUnexplored
+ ).thenOnServerThread(found -> {
+ if (found == null) {
+ afterComplete.accept(null);
+ return;
+ }
+ afterComplete.accept(new CraftStructureSearchResult(CraftStructure.minecraftToBukkit(found.getSecond().value()), CraftLocation.toBukkit(found.getFirst(), this)));
+ });
+ }
+ // Leaf end - Async structure locate api
+
// Paper start
@Override
public double getCoordinateScale() {

0 comments on commit a8ec234

Please sign in to comment.