diff --git a/src/main/java/world/bentobox/greenhouses/Greenhouses.java b/src/main/java/world/bentobox/greenhouses/Greenhouses.java index d3ed568..995bddb 100644 --- a/src/main/java/world/bentobox/greenhouses/Greenhouses.java +++ b/src/main/java/world/bentobox/greenhouses/Greenhouses.java @@ -11,6 +11,7 @@ import world.bentobox.bentobox.api.configuration.Config; import world.bentobox.bentobox.api.flags.Flag; import world.bentobox.bentobox.api.flags.Flag.Mode; import world.bentobox.bentobox.api.flags.Flag.Type; +import world.bentobox.greenhouses.greenhouse.Walls; import world.bentobox.greenhouses.managers.GreenhouseManager; import world.bentobox.greenhouses.managers.RecipeManager; import world.bentobox.greenhouses.ui.user.UserCommand; @@ -28,19 +29,13 @@ public class Greenhouses extends Addon { public static final Flag GREENHOUSES = new Flag.Builder("GREENHOUSE", Material.GREEN_STAINED_GLASS) .mode(Mode.BASIC) .type(Type.PROTECTION).build(); - private static Greenhouses instance; private final Config config; - public static Greenhouses getInstance() { - return instance; - } - /** * Constructor */ public Greenhouses() { super(); - instance = this; config = new Config<>(this, Settings.class); } @@ -122,4 +117,15 @@ public class Greenhouses extends Addon { return activeWorlds; } + /** + * Check if material is a wall material + * @param m - material + * @return true if wall material + */ + public boolean wallBlocks(Material m) { + return Walls.WALL_BLOCKS.contains(m) + || (m.equals(Material.GLOWSTONE) && getSettings().isAllowGlowstone()) + || (m.name().endsWith("GLASS_PANE") && getSettings().isAllowPanes()); + } + } diff --git a/src/main/java/world/bentobox/greenhouses/greenhouse/BiomeRecipe.java b/src/main/java/world/bentobox/greenhouses/greenhouse/BiomeRecipe.java index a589f77..998a0d5 100644 --- a/src/main/java/world/bentobox/greenhouses/greenhouse/BiomeRecipe.java +++ b/src/main/java/world/bentobox/greenhouses/greenhouse/BiomeRecipe.java @@ -209,7 +209,7 @@ public class BiomeRecipe implements Comparable { * @return set of results from the check */ private Set checkRecipeAsync(CompletableFuture> r, Greenhouse gh) { - AsyncWorldCache cache = new AsyncWorldCache(gh.getWorld()); + AsyncWorldCache cache = new AsyncWorldCache(addon, gh.getWorld()); Set result = new HashSet<>(); long area = gh.getArea(); Map blockCount = new EnumMap<>(Material.class); diff --git a/src/main/java/world/bentobox/greenhouses/greenhouse/Roof.java b/src/main/java/world/bentobox/greenhouses/greenhouse/Roof.java index 1a62454..474e16b 100644 --- a/src/main/java/world/bentobox/greenhouses/greenhouse/Roof.java +++ b/src/main/java/world/bentobox/greenhouses/greenhouse/Roof.java @@ -23,33 +23,17 @@ import world.bentobox.greenhouses.world.AsyncWorldCache; * @author tastybento * */ -@SuppressWarnings("deprecation") public class Roof extends MinMaxXZ { - private static final List ROOF_BLOCKS; - static { - // Roof blocks - ROOF_BLOCKS = Arrays.stream(Material.values()) - .filter(m -> !m.isLegacy()) - .filter(Material::isBlock) // Blocks only, no items - .filter(m -> Tag.TRAPDOORS.isTagged(m) // All trapdoors - || (m.name().contains("GLASS") && !m.name().contains("GLASS_PANE")) // All glass blocks - || m.equals(Material.HOPPER)).toList(); - } - /** - * Check if material is a roof material - * @param m - material - * @return true if roof material - */ - public static boolean roofBlocks(@NonNull Material m) { - return ROOF_BLOCKS.contains(Objects.requireNonNull(m)) - || (m.equals(Material.GLOWSTONE) && Greenhouses.getInstance().getSettings().isAllowGlowstone()) - || (m.name().endsWith("GLASS_PANE") && Greenhouses.getInstance().getSettings().isAllowPanes()); - } + private static final List ROOF_BLOCKS = Arrays.stream(Material.values()) + .filter(Material::isBlock) // Blocks only, no items + .filter(m -> Tag.TRAPDOORS.isTagged(m) // All trapdoors + || (m.name().contains("GLASS") && !m.name().contains("GLASS_PANE")) // All glass blocks + || m.equals(Material.HOPPER)).toList(); private final AsyncWorldCache cache; private int height; private final Location location; private boolean roofFound; - + private final Greenhouses addon; private final World world; @@ -58,13 +42,23 @@ public class Roof extends MinMaxXZ { * @param cache async world cache * @param loc - starting location */ - public Roof(AsyncWorldCache cache, Location loc) { + public Roof(AsyncWorldCache cache, Location loc, Greenhouses addon) { this.cache = cache; this.location = loc; + this.addon = addon; this.world = loc.getWorld(); } - + /** + * Check if material is a roof material + * @param m - material + * @return true if roof material + */ + public boolean roofBlocks(@NonNull Material m) { + return ROOF_BLOCKS.contains(Objects.requireNonNull(m)) + || (m.equals(Material.GLOWSTONE) && addon.getSettings().isAllowGlowstone()) + || (m.name().endsWith("GLASS_PANE") && addon.getSettings().isAllowPanes()); + } /** * This takes any location and tries to go as far as possible in NWSE directions finding contiguous roof blocks @@ -211,7 +205,7 @@ public class Roof extends MinMaxXZ { * @param z - z coord of current search */ private Optional checkVertically(final int x, final int startY, final int z) { - if (!Walls.wallBlocks(cache.getBlockType(x, startY, z))) { + if (!addon.wallBlocks(cache.getBlockType(x, startY, z))) { // Look up for (int y = startY; y < world.getMaxHeight() && !roofFound; y++) { if (roofBlocks(cache.getBlockType(x,y,z))) { diff --git a/src/main/java/world/bentobox/greenhouses/greenhouse/Walls.java b/src/main/java/world/bentobox/greenhouses/greenhouse/Walls.java index d4a0890..1f34937 100644 --- a/src/main/java/world/bentobox/greenhouses/greenhouse/Walls.java +++ b/src/main/java/world/bentobox/greenhouses/greenhouse/Walls.java @@ -9,25 +9,17 @@ import org.bukkit.Location; import org.bukkit.Material; import world.bentobox.bentobox.BentoBox; -import world.bentobox.greenhouses.Greenhouses; import world.bentobox.greenhouses.world.AsyncWorldCache; -@SuppressWarnings("deprecation") public class Walls extends MinMaxXZ { - private static final List WALL_BLOCKS; - static { - // Hoppers - WALL_BLOCKS = Arrays.stream(Material.values()) - .filter(Material::isBlock) // Blocks only, no items - .filter(m -> !m.isLegacy()) - .filter(m -> !m.name().contains("TRAPDOOR")) // No trap doors - .filter(m -> m.name().contains("DOOR") // All doors - || (m.name().contains("GLASS") && !m.name().contains("GLASS_PANE")) // All glass blocks - || m.equals(Material.HOPPER)).toList(); - } + public static final List WALL_BLOCKS = Arrays.stream(Material.values()) + .filter(Material::isBlock) // Blocks only, no items + .filter(m -> !m.name().contains("TRAPDOOR")) // No trap doors + .filter(m -> m.name().contains("DOOR") // All doors + || (m.name().contains("GLASS") && !m.name().contains("GLASS_PANE")) // All glass blocks + || m.equals(Material.HOPPER)).toList(); private int floor; - private final AsyncWorldCache cache; static class WallFinder { @@ -177,17 +169,6 @@ public class Walls extends MinMaxXZ { } - /** - * Check if material is a wall material - * @param m - material - * @return true if wall material - */ - public static boolean wallBlocks(Material m) { - return WALL_BLOCKS.contains(m) - || (m.equals(Material.GLOWSTONE) && Greenhouses.getInstance().getSettings().isAllowGlowstone()) - || (m.name().endsWith("GLASS_PANE") && Greenhouses.getInstance().getSettings().isAllowPanes()); - } - /** * @return the floor */ diff --git a/src/main/java/world/bentobox/greenhouses/managers/GreenhouseFinder.java b/src/main/java/world/bentobox/greenhouses/managers/GreenhouseFinder.java index e7b29f5..37257ed 100644 --- a/src/main/java/world/bentobox/greenhouses/managers/GreenhouseFinder.java +++ b/src/main/java/world/bentobox/greenhouses/managers/GreenhouseFinder.java @@ -12,6 +12,7 @@ import org.bukkit.Tag; import org.bukkit.util.Vector; import world.bentobox.bentobox.BentoBox; +import world.bentobox.greenhouses.Greenhouses; import world.bentobox.greenhouses.data.Greenhouse; import world.bentobox.greenhouses.greenhouse.Roof; import world.bentobox.greenhouses.greenhouse.Walls; @@ -28,10 +29,12 @@ public class GreenhouseFinder { // If this is the bottom layer, the player has most likely uneven walls private int otherBlockLayer = -1; private int wallBlockCount; + private final Greenhouses addon; /** * This is the count of the various items */ private CounterCheck cc = new CounterCheck(); + private Roof roof; static class CounterCheck { int doorCount; @@ -40,6 +43,13 @@ public class GreenhouseFinder { boolean otherBlock; } + /** + * @param addon + */ + public GreenhouseFinder(Greenhouses addon) { + this.addon = addon; + } + /** * Find out if there is a greenhouse here * @param location - start location @@ -51,9 +61,9 @@ public class GreenhouseFinder { redGlass.clear(); // Get a world cache - AsyncWorldCache cache = new AsyncWorldCache(location.getWorld()); + AsyncWorldCache cache = new AsyncWorldCache(addon, location.getWorld()); // Find the roof - Roof roof = new Roof(cache, location); + roof = new Roof(cache, location, addon); roof.findRoof().thenAccept(found -> { if (Boolean.FALSE.equals(found)) { result.add(GreenhouseResult.FAIL_NO_ROOF); @@ -166,7 +176,8 @@ public class GreenhouseFinder { // Check wall blocks only if (y == roof.getHeight() || x == walls.getMinX() || x == walls.getMaxX() || z == walls.getMinZ() || z== walls.getMaxZ()) { // Check for non-wall blocks or non-roof blocks at the top of walls - if ((y != roof.getHeight() && !Walls.wallBlocks(m)) || (y == roof.getHeight() && !Roof.roofBlocks(m))) { + if ((y != roof.getHeight() && !addon.wallBlocks(m)) + || (y == roof.getHeight() && !roof.roofBlocks(m))) { if (m.equals(Material.AIR)) { // Air hole found cc.airHole = true; diff --git a/src/main/java/world/bentobox/greenhouses/managers/GreenhouseManager.java b/src/main/java/world/bentobox/greenhouses/managers/GreenhouseManager.java index a18e569..13f1e70 100644 --- a/src/main/java/world/bentobox/greenhouses/managers/GreenhouseManager.java +++ b/src/main/java/world/bentobox/greenhouses/managers/GreenhouseManager.java @@ -96,19 +96,19 @@ public class GreenhouseManager implements Listener { handler.loadObjects().forEach(g -> { GreenhouseResult result = map.addGreenhouse(g); switch (result) { - case FAIL_NO_ISLAND -> - // Delete the failed greenhouse - toBeRemoved.add(g); - case FAIL_OVERLAPPING -> addon.logError("Greenhouse overlaps with another greenhouse. Skipping..."); - case NULL -> addon.logError("Null location of greenhouse. Cannot load. Skipping..."); - case SUCCESS -> activateGreenhouse(g); - case FAIL_NO_WORLD -> addon.logError("Database contains greenhouse for a non-loaded world. Skipping..."); - case FAIL_UNKNOWN_RECIPE -> { - addon.logError("Greenhouse uses a recipe that does not exist in the biomes.yml. Skipping..."); - addon.logError("Greenhouse Id " + g.getUniqueId()); - } - default -> { - } + case FAIL_NO_ISLAND -> + // Delete the failed greenhouse + toBeRemoved.add(g); + case FAIL_OVERLAPPING -> addon.logError("Greenhouse overlaps with another greenhouse. Skipping..."); + case NULL -> addon.logError("Null location of greenhouse. Cannot load. Skipping..."); + case SUCCESS -> activateGreenhouse(g); + case FAIL_NO_WORLD -> addon.logError("Database contains greenhouse for a non-loaded world. Skipping..."); + case FAIL_UNKNOWN_RECIPE -> { + addon.logError("Greenhouse uses a recipe that does not exist in the biomes.yml. Skipping..."); + addon.logError("Greenhouse Id " + g.getUniqueId()); + } + default -> { + } } }); addon.log("Loaded " + map.getSize() + " greenhouses."); @@ -153,7 +153,7 @@ public class GreenhouseManager implements Listener { */ public CompletableFuture tryToMakeGreenhouse(Location location, BiomeRecipe greenhouseRecipe) { CompletableFuture r = new CompletableFuture<>(); - GreenhouseFinder finder = new GreenhouseFinder(); + GreenhouseFinder finder = new GreenhouseFinder(addon); finder.find(location).thenAccept(resultSet -> { if (!resultSet.isEmpty()) { // Failure! diff --git a/src/main/java/world/bentobox/greenhouses/world/AsyncWorldCache.java b/src/main/java/world/bentobox/greenhouses/world/AsyncWorldCache.java index 05c5ce0..4313fbc 100644 --- a/src/main/java/world/bentobox/greenhouses/world/AsyncWorldCache.java +++ b/src/main/java/world/bentobox/greenhouses/world/AsyncWorldCache.java @@ -27,14 +27,16 @@ public class AsyncWorldCache { private final World world; private final Map, ChunkSnapshot> cache; + private final Greenhouses addon; /** * Chunk cache. This class is designed to be run async and blocks futures * @param world - world to cache */ - public AsyncWorldCache(World world) { + public AsyncWorldCache(Greenhouses addon, World world) { this.world = world; cache = new HashMap<>(); + this.addon = addon; } /** @@ -59,7 +61,7 @@ public class AsyncWorldCache { */ private CompletableFuture getAChunk(int x, int z) { CompletableFuture r = new CompletableFuture<>(); - Bukkit.getScheduler().runTask(Greenhouses.getInstance().getPlugin(), () -> + Bukkit.getScheduler().runTask(addon.getPlugin(), () -> Util.getChunkAtAsync(world, x, z).thenAccept(chunk -> r.complete(chunk.getChunkSnapshot()))); return r; } @@ -104,7 +106,7 @@ public class AsyncWorldCache { try { return Objects.requireNonNull(getSnap(x, z)).getBlockType(xx, y, zz); } catch (InterruptedException | ExecutionException e) { - Greenhouses.getInstance().logError("Chunk could not be obtained async! " + e); + addon.logError("Chunk could not be obtained async! " + e); // Restore interrupted state... Thread.currentThread().interrupt(); return Material.AIR; diff --git a/src/test/java/world/bentobox/greenhouses/greenhouse/RoofTest.java b/src/test/java/world/bentobox/greenhouses/greenhouse/RoofTest.java index 8b23894..b21e5e8 100644 --- a/src/test/java/world/bentobox/greenhouses/greenhouse/RoofTest.java +++ b/src/test/java/world/bentobox/greenhouses/greenhouse/RoofTest.java @@ -50,8 +50,6 @@ public class RoofTest { public void setUp() { PowerMockito.mockStatic(Bukkit.class, Mockito.RETURNS_MOCKS); when(Tag.TRAPDOORS.isTagged(Material.BIRCH_TRAPDOOR)).thenReturn(true); - PowerMockito.mockStatic(Greenhouses.class, Mockito.RETURNS_MOCKS); - when(Greenhouses.getInstance()).thenReturn(addon); s = new Settings(); when(addon.getSettings()).thenReturn(s); @@ -89,14 +87,14 @@ public class RoofTest { when(location.clone()).thenReturn(location); // Test - roof = new Roof(cache, location); + roof = new Roof(cache, location, addon); assertTrue(roof.findRoof(new Vector(10,10,10))); } @Test public void testNoGlass() { when(cache.getBlockType(anyInt(), anyInt(), anyInt())).thenReturn(Material.AIR); - roof = new Roof(cache, location); + roof = new Roof(cache, location, addon); assertFalse(roof.findRoof(new Vector(10,10,10))); } @@ -169,13 +167,13 @@ public class RoofTest { */ @Test public void testWallBlocks() { - assertFalse(Roof.roofBlocks(Material.ACACIA_BOAT)); - assertTrue(Roof.roofBlocks(Material.GLASS)); - assertTrue(Roof.roofBlocks(Material.GLOWSTONE)); - assertFalse(Roof.roofBlocks(Material.ACACIA_DOOR)); - assertTrue(Roof.roofBlocks(Material.HOPPER)); - assertTrue(Roof.roofBlocks(Material.PURPLE_STAINED_GLASS_PANE)); - assertTrue(Roof.roofBlocks(Material.BIRCH_TRAPDOOR)); + assertFalse(roof.roofBlocks(Material.ACACIA_BOAT)); + assertTrue(roof.roofBlocks(Material.GLASS)); + assertTrue(roof.roofBlocks(Material.GLOWSTONE)); + assertFalse(roof.roofBlocks(Material.ACACIA_DOOR)); + assertTrue(roof.roofBlocks(Material.HOPPER)); + assertTrue(roof.roofBlocks(Material.PURPLE_STAINED_GLASS_PANE)); + assertTrue(roof.roofBlocks(Material.BIRCH_TRAPDOOR)); } /** @@ -185,12 +183,12 @@ public class RoofTest { public void testWallBlocksNoGlowStoneNoPanes() { s.setAllowGlowstone(false); s.setAllowPanes(false); - assertFalse(Roof.roofBlocks(Material.ACACIA_BOAT)); - assertTrue(Roof.roofBlocks(Material.GLASS)); - assertFalse(Roof.roofBlocks(Material.GLOWSTONE)); - assertFalse(Roof.roofBlocks(Material.ACACIA_DOOR)); - assertTrue(Roof.roofBlocks(Material.HOPPER)); - assertFalse(Roof.roofBlocks(Material.PURPLE_STAINED_GLASS_PANE)); - assertTrue(Roof.roofBlocks(Material.BIRCH_TRAPDOOR)); + assertFalse(roof.roofBlocks(Material.ACACIA_BOAT)); + assertTrue(roof.roofBlocks(Material.GLASS)); + assertFalse(roof.roofBlocks(Material.GLOWSTONE)); + assertFalse(roof.roofBlocks(Material.ACACIA_DOOR)); + assertTrue(roof.roofBlocks(Material.HOPPER)); + assertFalse(roof.roofBlocks(Material.PURPLE_STAINED_GLASS_PANE)); + assertTrue(roof.roofBlocks(Material.BIRCH_TRAPDOOR)); } } diff --git a/src/test/java/world/bentobox/greenhouses/greenhouse/WallsTest.java b/src/test/java/world/bentobox/greenhouses/greenhouse/WallsTest.java index 7231f34..5e4d279 100644 --- a/src/test/java/world/bentobox/greenhouses/greenhouse/WallsTest.java +++ b/src/test/java/world/bentobox/greenhouses/greenhouse/WallsTest.java @@ -64,12 +64,10 @@ public class WallsTest { when(Tag.TRAPDOORS.isTagged(Material.BIRCH_TRAPDOOR)).thenReturn(true); // Declare mock after mocking Bukkit roof = mock(Roof.class); - PowerMockito.mockStatic(Greenhouses.class, Mockito.RETURNS_MOCKS); - when(Greenhouses.getInstance()).thenReturn(addon); s = new Settings(); when(addon.getSettings()).thenReturn(s); when(addon.getPlugin()).thenReturn(plugin); - + when(addon.wallBlocks(any())).thenCallRealMethod(); walls = new Walls(cache); when(world.getMaxHeight()).thenReturn(255); when(location.getWorld()).thenReturn(world); @@ -201,13 +199,13 @@ public class WallsTest { */ @Test public void testWallBlocks() { - assertFalse(Walls.wallBlocks(Material.ACACIA_BOAT)); - assertTrue(Walls.wallBlocks(Material.GLASS)); - assertTrue(Walls.wallBlocks(Material.GLOWSTONE)); - assertTrue(Walls.wallBlocks(Material.ACACIA_DOOR)); - assertTrue(Walls.wallBlocks(Material.HOPPER)); - assertTrue(Walls.wallBlocks(Material.PURPLE_STAINED_GLASS_PANE)); - assertFalse(Walls.wallBlocks(Material.BIRCH_TRAPDOOR)); + assertFalse(addon.wallBlocks(Material.ACACIA_BOAT)); + assertTrue(addon.wallBlocks(Material.GLASS)); + assertTrue(addon.wallBlocks(Material.GLOWSTONE)); + assertTrue(addon.wallBlocks(Material.ACACIA_DOOR)); + assertTrue(addon.wallBlocks(Material.HOPPER)); + assertTrue(addon.wallBlocks(Material.PURPLE_STAINED_GLASS_PANE)); + assertFalse(addon.wallBlocks(Material.BIRCH_TRAPDOOR)); } /** @@ -217,13 +215,13 @@ public class WallsTest { public void testWallBlocksNoGlowStoneNoPanes() { s.setAllowGlowstone(false); s.setAllowPanes(false); - assertFalse(Walls.wallBlocks(Material.ACACIA_BOAT)); - assertTrue(Walls.wallBlocks(Material.GLASS)); - assertFalse(Walls.wallBlocks(Material.GLOWSTONE)); - assertTrue(Walls.wallBlocks(Material.ACACIA_DOOR)); - assertTrue(Walls.wallBlocks(Material.HOPPER)); - assertFalse(Walls.wallBlocks(Material.PURPLE_STAINED_GLASS_PANE)); - assertFalse(Walls.wallBlocks(Material.BIRCH_TRAPDOOR)); + assertFalse(addon.wallBlocks(Material.ACACIA_BOAT)); + assertTrue(addon.wallBlocks(Material.GLASS)); + assertFalse(addon.wallBlocks(Material.GLOWSTONE)); + assertTrue(addon.wallBlocks(Material.ACACIA_DOOR)); + assertTrue(addon.wallBlocks(Material.HOPPER)); + assertFalse(addon.wallBlocks(Material.PURPLE_STAINED_GLASS_PANE)); + assertFalse(addon.wallBlocks(Material.BIRCH_TRAPDOOR)); } /** diff --git a/src/test/java/world/bentobox/greenhouses/managers/GreenhouseFinderTest.java b/src/test/java/world/bentobox/greenhouses/managers/GreenhouseFinderTest.java index ca8139f..d081a12 100644 --- a/src/test/java/world/bentobox/greenhouses/managers/GreenhouseFinderTest.java +++ b/src/test/java/world/bentobox/greenhouses/managers/GreenhouseFinderTest.java @@ -71,12 +71,14 @@ public class GreenhouseFinderTest { when(Tag.TRAPDOORS.isTagged(Material.BIRCH_TRAPDOOR)).thenReturn(true); // Declare mock after mocking Bukkit roof = mock(Roof.class); + when(roof.roofBlocks(any())).thenCallRealMethod(); // Location when(location.getBlockX()).thenReturn(5); when(location.getBlockY()).thenReturn(14); when(location.getBlockZ()).thenReturn(25); when(location.getWorld()).thenReturn(world); - + // Addon + when(addon.wallBlocks(any())).thenCallRealMethod(); // Block when(cache.getBlockType(any())).thenReturn(Material.GLASS); when(cache.getBlockType(anyInt(), anyInt(), anyInt())).thenReturn(Material.GLASS); @@ -94,7 +96,7 @@ public class GreenhouseFinderTest { when(cache.getMaxHeight()).thenReturn(30); - gf = new GreenhouseFinder(); + gf = new GreenhouseFinder(addon); cc = new CounterCheck(); }