Made greenhouse ecosystem checking async.

https://github.com/BentoBoxWorld/Greenhouses/issues/68
This commit is contained in:
tastybento 2021-01-17 08:41:50 -08:00
parent cd5a0ce2a1
commit 27df88aaf3
4 changed files with 51 additions and 30 deletions

View File

@ -10,8 +10,10 @@ import java.util.Optional;
import java.util.Random;
import java.util.Set;
import java.util.TreeMap;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.Particle;
@ -36,6 +38,7 @@ import world.bentobox.bentobox.util.Util;
import world.bentobox.greenhouses.Greenhouses;
import world.bentobox.greenhouses.data.Greenhouse;
import world.bentobox.greenhouses.managers.GreenhouseManager.GreenhouseResult;
import world.bentobox.greenhouses.world.AsyncWorldCache;
public class BiomeRecipe implements Comparable<BiomeRecipe> {
private static final String CHANCE_FOR = "% chance for ";
@ -155,21 +158,34 @@ public class BiomeRecipe implements Comparable<BiomeRecipe> {
startupLog(" " + blockMaterial + " x " + blockQty);
}
// Check required blocks
/**
* Checks greenhouse meets recipe requirements.
* @return GreenhouseResult - result
*/
public Set<GreenhouseResult> checkRecipe(Greenhouse gh) {
public CompletableFuture<Set<GreenhouseResult>> checkRecipe(Greenhouse gh) {
CompletableFuture<Set<GreenhouseResult>> r = new CompletableFuture<>();
Bukkit.getScheduler().runTaskAsynchronously(addon.getPlugin(), () -> checkRecipeAsync(r, gh));
return r;
}
/**
* Check greenhouse meets recipe requirements. Expected to be run async.
* @param r - future to complete when done
* @param gh - greenhouse
* @return set of results from the check
*/
private Set<GreenhouseResult> checkRecipeAsync(CompletableFuture<Set<GreenhouseResult>> r, Greenhouse gh) {
AsyncWorldCache cache = new AsyncWorldCache(gh.getWorld());
Set<GreenhouseResult> result = new HashSet<>();
long area = gh.getArea();
Map<Material, Integer> blockCount = new EnumMap<>(Material.class);
// Look through the greenhouse and count what is in there
for (int y = gh.getFloorHeight(); y< gh.getCeilingHeight();y++) {
for (int x = (int) (gh.getBoundingBox().getMinX()+1); x < gh.getBoundingBox().getMaxX(); x++) {
for (int z = (int) (gh.getBoundingBox().getMinZ()+1); z < gh.getBoundingBox().getMaxZ(); z++) {
Block b = gh.getWorld().getBlockAt(x, y, z);
Material t = b.getType();
Material t = cache.getBlockType(x, y, z);
if (!t.equals(Material.AIR)) {
blockCount.putIfAbsent(t, 0);
blockCount.merge(t, 1, Integer::sum);
@ -213,6 +229,8 @@ public class BiomeRecipe implements Comparable<BiomeRecipe> {
result.add(GreenhouseResult.FAIL_INSUFFICIENT_BLOCKS);
gh.setMissingBlocks(missingBlocks);
}
// Return to main thread to complete
Bukkit.getScheduler().runTask(addon.getPlugin(), () -> r.complete(result));
return result;
}

View File

@ -101,10 +101,13 @@ public class EcoSystemManager {
//addon.log("Skipping verify for unloaded greenhouse at " + gh.getLocation());
return;
}
if (!gh.getBiomeRecipe().checkRecipe(gh).isEmpty()) {
addon.log("Greenhouse failed verification at " + gh.getLocation());
g.removeGreenhouse(gh);
}
gh.getBiomeRecipe().checkRecipe(gh).thenAccept(rs -> {
if (!rs.isEmpty()) {
addon.log("Greenhouse failed verification at " + gh.getLocation());
g.removeGreenhouse(gh);
}
});
}
private void addMobs(Greenhouse gh) {

View File

@ -167,10 +167,9 @@ public class GreenhouseManager implements Listener {
}
// Check if the greenhouse meets the requested recipe
if (greenhouseRecipe != null) {
checkRecipe(r, finder, greenhouseRecipe, resultSet);
checkRecipe(finder, greenhouseRecipe, resultSet).thenAccept(r::complete);
return;
}
// Try ordered recipes
findRecipe(finder, resultSet);
r.complete(new GhResult().setFinder(finder).setResults(resultSet));
@ -184,6 +183,8 @@ public class GreenhouseManager implements Listener {
* @param resultSet - result set from find
*/
private void findRecipe(GreenhouseFinder finder, Set<GreenhouseResult> resultSet) {
// TODO
/*
resultSet.add(addon.getRecipes().getBiomeRecipes().stream().sorted()
.filter(r -> r.checkRecipe(finder.getGh()).isEmpty()).findFirst()
.map(r -> {
@ -192,7 +193,7 @@ public class GreenhouseManager implements Listener {
activateGreenhouse(finder.getGh());
handler.saveObjectAsync(finder.getGh());
return map.addGreenhouse(finder.getGh());
}).orElse(GreenhouseResult.FAIL_NO_RECIPE_FOUND));
}).orElse(GreenhouseResult.FAIL_NO_RECIPE_FOUND));*/
}
/**
@ -203,19 +204,20 @@ public class GreenhouseManager implements Listener {
* @param resultSet - result set from finder
* @return Greenhouse result
*/
GhResult checkRecipe(CompletableFuture<GhResult> r, GreenhouseFinder finder, BiomeRecipe greenhouseRecipe, Set<GreenhouseResult> resultSet) {
resultSet = greenhouseRecipe.checkRecipe(finder.getGh());
if (resultSet.isEmpty()) {
// Success - set recipe and add to map
finder.getGh().setBiomeRecipe(greenhouseRecipe);
resultSet.add(map.addGreenhouse(finder.getGh()));
activateGreenhouse(finder.getGh());
handler.saveObjectAsync(finder.getGh());
}
GhResult recipe = new GhResult().setFinder(finder).setResults(resultSet);
r.complete(recipe);
return recipe;
CompletableFuture<GhResult> checkRecipe(GreenhouseFinder finder, BiomeRecipe greenhouseRecipe, Set<GreenhouseResult> resultSet) {
CompletableFuture<GhResult> r = new CompletableFuture<>();
greenhouseRecipe.checkRecipe(finder.getGh()).thenAccept(rs -> {
if (rs.isEmpty()) {
// Success - set recipe and add to map
finder.getGh().setBiomeRecipe(greenhouseRecipe);
resultSet.add(map.addGreenhouse(finder.getGh()));
activateGreenhouse(finder.getGh());
handler.saveObjectAsync(finder.getGh());
}
GhResult recipe = new GhResult().setFinder(finder).setResults(rs);
r.complete(recipe);
});
return r;
}
private void activateGreenhouse(Greenhouse gh) {

View File

@ -13,7 +13,6 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.util.Optional;
import java.util.Set;
import org.bukkit.Bukkit;
import org.bukkit.Location;
@ -48,7 +47,6 @@ import world.bentobox.greenhouses.Greenhouses;
import world.bentobox.greenhouses.Settings;
import world.bentobox.greenhouses.data.Greenhouse;
import world.bentobox.greenhouses.managers.GreenhouseManager;
import world.bentobox.greenhouses.managers.GreenhouseManager.GreenhouseResult;
import world.bentobox.greenhouses.managers.GreenhouseMap;
/**
@ -237,8 +235,8 @@ public class BiomeRecipeTest {
*/
@Test
public void testCheckRecipe() {
Set<GreenhouseResult> result = br.checkRecipe(gh);
assertTrue(result.isEmpty());
br.checkRecipe(gh).thenAccept(result ->
assertTrue(result.isEmpty()));
}
/**
@ -247,8 +245,8 @@ public class BiomeRecipeTest {
@Test
public void testCheckRecipeNotEnough() {
br.addReqBlocks(Material.ACACIA_LEAVES, 3);
Set<GreenhouseResult> result = br.checkRecipe(gh);
assertFalse(result.isEmpty());
br.checkRecipe(gh).thenAccept(result ->
assertFalse(result.isEmpty()));
}