From 818f6fc925ec7485f03e467abf0aa9dd58d3578b Mon Sep 17 00:00:00 2001 From: tastybento Date: Sun, 1 Aug 2021 16:17:12 -0700 Subject: [PATCH] Null checks. --- .../bentobox/greenhouses/data/Greenhouse.java | 13 +++++--- .../listeners/GreenhouseEvents.java | 8 +++++ .../greenhouses/listeners/SnowTracker.java | 10 +++++- .../managers/EcoSystemManager.java | 33 ++++++++++++------- .../managers/GreenhouseManager.java | 8 +++++ .../greenhouses/managers/GreenhouseMap.java | 12 ++++--- .../greenhouses/ui/panel/PanelClick.java | 4 +++ .../greenhouses/ui/user/MakeCommand.java | 4 +++ .../greenhouses/ui/user/RemoveCommand.java | 4 +++ .../greenhouses/world/AsyncWorldCache.java | 3 +- .../greenhouses/data/GreenhouseTest.java | 2 +- 11 files changed, 77 insertions(+), 24 deletions(-) diff --git a/src/main/java/world/bentobox/greenhouses/data/Greenhouse.java b/src/main/java/world/bentobox/greenhouses/data/Greenhouse.java index dc504dc..158ab9c 100644 --- a/src/main/java/world/bentobox/greenhouses/data/Greenhouse.java +++ b/src/main/java/world/bentobox/greenhouses/data/Greenhouse.java @@ -1,5 +1,6 @@ package world.bentobox.greenhouses.data; +import java.util.HashMap; import java.util.Map; import java.util.Objects; import java.util.UUID; @@ -158,7 +159,11 @@ public class Greenhouse implements DataObject { * @param v the roofHopperLocation to set */ public void setRoofHopperLocation(@Nullable Vector v) { - this.roofHopperLocation = v == null ? null : v.toLocation(getWorld()); + if (v == null || getWorld() == null) { + this.roofHopperLocation = null; + } else { + this.roofHopperLocation = v.toLocation(getWorld()); + } } /** @@ -206,7 +211,7 @@ public class Greenhouse implements DataObject { */ @Nullable public World getWorld() { - return this.getLocation().getWorld(); + return this.getLocation() == null ? null : this.getLocation().getWorld(); } /** @@ -246,9 +251,9 @@ public class Greenhouse implements DataObject { /** * @return the missingBlocks */ - @Nullable + @NonNull public Map getMissingBlocks() { - return missingBlocks; + return Objects.requireNonNullElseGet(missingBlocks, () -> new HashMap<>()); } /** diff --git a/src/main/java/world/bentobox/greenhouses/listeners/GreenhouseEvents.java b/src/main/java/world/bentobox/greenhouses/listeners/GreenhouseEvents.java index 21a667b..1c77055 100644 --- a/src/main/java/world/bentobox/greenhouses/listeners/GreenhouseEvents.java +++ b/src/main/java/world/bentobox/greenhouses/listeners/GreenhouseEvents.java @@ -108,7 +108,15 @@ public class GreenhouseEvents implements Listener { handleTransition(User.getInstance(e.getPlayer()), e.getTo(), e.getFrom()); } + /** + * @param user user + * @param toLoc to location + * @param fromLoc from location + */ private void handleTransition(User user, Location toLoc, Location fromLoc) { + if (user == null) { + return; + } Optional to = addon.getManager().getMap().getGreenhouse(toLoc); Optional from = addon.getManager().getMap().getGreenhouse(fromLoc); if (to.isEmpty() && from.isEmpty()) { diff --git a/src/main/java/world/bentobox/greenhouses/listeners/SnowTracker.java b/src/main/java/world/bentobox/greenhouses/listeners/SnowTracker.java index 2386546..932fc71 100644 --- a/src/main/java/world/bentobox/greenhouses/listeners/SnowTracker.java +++ b/src/main/java/world/bentobox/greenhouses/listeners/SnowTracker.java @@ -41,7 +41,15 @@ public class SnowTracker implements Listener { } + /** + * @param gh - greenhouse + * @return true if snow was create, false if not. + */ private boolean getAirBlocks(Greenhouse gh) { + if (gh.getLocation() == null) { + // Greenhouse does not have a location for some reason. + return false; + } boolean createdSnow = false; List waterBlocks = new ArrayList<>(); for (int x = (int)gh.getBoundingBox().getMinX() + 1; x < (int)gh.getBoundingBox().getMaxX() -1; x++) { @@ -108,7 +116,7 @@ public class SnowTracker implements Listener { private void removeWaterBucketAndShake(Greenhouse g) { // Scatter snow - if (getAirBlocks(g)) { + if (getAirBlocks(g) && g.getRoofHopperLocation() != null) { Hopper h = ((Hopper)g.getRoofHopperLocation().getBlock().getState()); h.getInventory().removeItem(new ItemStack(Material.WATER_BUCKET)); h.getInventory().addItem(new ItemStack(Material.BUCKET)); diff --git a/src/main/java/world/bentobox/greenhouses/managers/EcoSystemManager.java b/src/main/java/world/bentobox/greenhouses/managers/EcoSystemManager.java index 48ee6ff..8f201c7 100644 --- a/src/main/java/world/bentobox/greenhouses/managers/EcoSystemManager.java +++ b/src/main/java/world/bentobox/greenhouses/managers/EcoSystemManager.java @@ -85,7 +85,10 @@ public class EcoSystemManager { } private void convertBlocks(Greenhouse gh) { - if(!gh.getLocation().getWorld().isChunkLoaded(((int) gh.getBoundingBox().getMaxX()) >> 4, ((int) gh.getBoundingBox().getMaxZ()) >> 4) || !gh.getLocation().getWorld().isChunkLoaded(((int) gh.getBoundingBox().getMinX()) >> 4, ((int) gh.getBoundingBox().getMinZ()) >> 4)){ + World world = gh.getWorld(); + if(world == null || gh.getLocation() == null || gh.getLocation().getWorld() == null + || !gh.getLocation().getWorld().isChunkLoaded(((int) gh.getBoundingBox().getMaxX()) >> 4, ((int) gh.getBoundingBox().getMaxZ()) >> 4) + || !gh.getLocation().getWorld().isChunkLoaded(((int) gh.getBoundingBox().getMinX()) >> 4, ((int) gh.getBoundingBox().getMinZ()) >> 4)){ return; } @@ -95,7 +98,6 @@ public class EcoSystemManager { int gh_max_y = NumberConversions.floor(gh.getInternalBoundingBox().getMaxY()); int gh_min_z = NumberConversions.floor(gh.getInternalBoundingBox().getMinZ()); int gh_max_z = NumberConversions.floor(gh.getInternalBoundingBox().getMaxZ()); - World world = gh.getWorld(); BiomeRecipe biomeRecipe = gh.getBiomeRecipe(); for (int x = gh_min_x; x < gh_max_x; x++) { @@ -112,8 +114,10 @@ public class EcoSystemManager { } private void verify(Greenhouse gh) { - if(!gh.getLocation().getWorld().isChunkLoaded(((int) gh.getBoundingBox().getMaxX()) >> 4, ((int) gh.getBoundingBox().getMaxZ()) >> 4) || !gh.getLocation().getWorld().isChunkLoaded(((int) gh.getBoundingBox().getMinX()) >> 4, ((int) gh.getBoundingBox().getMinZ()) >> 4)){ - //addon.log("Skipping verify for unloaded greenhouse at " + gh.getLocation()); + if(gh.getLocation() == null || gh.getLocation().getWorld() == null + || !gh.getLocation().getWorld().isChunkLoaded(((int) gh.getBoundingBox().getMaxX()) >> 4, ((int) gh.getBoundingBox().getMaxZ()) >> 4) + || !gh.getLocation().getWorld().isChunkLoaded(((int) gh.getBoundingBox().getMinX()) >> 4, ((int) gh.getBoundingBox().getMinZ()) >> 4)){ + // Skipping verify for unloaded greenhouse return; } gh.getBiomeRecipe().checkRecipe(gh).thenAccept(rs -> { @@ -126,8 +130,9 @@ public class EcoSystemManager { } private void addMobs(Greenhouse gh) { - if(!gh.getLocation().getWorld().isChunkLoaded(((int) gh.getBoundingBox().getMaxX()) >> 4, ((int) gh.getBoundingBox().getMaxZ()) >> 4) || !gh.getLocation().getWorld().isChunkLoaded(((int) gh.getBoundingBox().getMinX()) >> 4, ((int) gh.getBoundingBox().getMinZ()) >> 4)){ - //addon.log("Skipping addmobs for unloaded greenhouse at " + gh.getLocation()); + if(gh.getLocation() == null || gh.getLocation().getWorld() == null || gh.getWorld() == null + || !gh.getLocation().getWorld().isChunkLoaded(((int) gh.getBoundingBox().getMaxX()) >> 4, ((int) gh.getBoundingBox().getMaxZ()) >> 4) || !gh.getLocation().getWorld().isChunkLoaded(((int) gh.getBoundingBox().getMinX()) >> 4, ((int) gh.getBoundingBox().getMinZ()) >> 4)){ + // Skipping addmobs for unloaded greenhouse return; } if (gh.getBiomeRecipe().noMobs()) { @@ -166,8 +171,9 @@ public class EcoSystemManager { * @param gh - greenhouse */ private void growPlants(Greenhouse gh) { - if(!gh.getLocation().getWorld().isChunkLoaded(((int) gh.getBoundingBox().getMaxX()) >> 4, ((int) gh.getBoundingBox().getMaxZ()) >> 4) || !gh.getLocation().getWorld().isChunkLoaded(((int) gh.getBoundingBox().getMinX()) >> 4, ((int) gh.getBoundingBox().getMinZ()) >> 4)){ - //addon.log("Skipping growplants for unloaded greenhouse at " + gh.getLocation()); + if (gh.getLocation() == null || gh.getLocation().getWorld() == null + || !gh.getLocation().getWorld().isChunkLoaded(((int) gh.getBoundingBox().getMaxX()) >> 4, ((int) gh.getBoundingBox().getMaxZ()) >> 4) || !gh.getLocation().getWorld().isChunkLoaded(((int) gh.getBoundingBox().getMinX()) >> 4, ((int) gh.getBoundingBox().getMinZ()) >> 4)){ + //Skipping growplants for unloaded greenhouse return; } int bonemeal = getBoneMeal(gh); @@ -207,6 +213,7 @@ public class EcoSystemManager { */ public List getAvailableBlocks(Greenhouse gh, boolean ignoreLiquid) { List result = new ArrayList<>(); + if (gh.getWorld() == null) return result; for (double x = gh.getInternalBoundingBox().getMinX(); x < gh.getInternalBoundingBox().getMaxX(); x++) { for (double z = gh.getInternalBoundingBox().getMinZ(); z < gh.getInternalBoundingBox().getMaxZ(); z++) { for (double y = gh.getInternalBoundingBox().getMaxY() - 1; y >= gh.getBoundingBox().getMinY(); y--) { @@ -234,12 +241,14 @@ public class EcoSystemManager { .mapToInt(ItemStack::getAmount).sum(); } + /** + * Get the hopper + * @param gh greenhouse + * @return hopper block or null if it does not exist + */ private Hopper getHopper(Greenhouse gh) { - if (gh.getRoofHopperLocation() == null) { - return null; - } // Check if the hopper block is still a hopper - if (gh.getRoofHopperLocation().getBlock().getType() != Material.HOPPER) { + if (gh.getRoofHopperLocation() == null || !gh.getRoofHopperLocation().getBlock().getType().equals(Material.HOPPER)) { gh.setRoofHopperLocation(null); return null; } diff --git a/src/main/java/world/bentobox/greenhouses/managers/GreenhouseManager.java b/src/main/java/world/bentobox/greenhouses/managers/GreenhouseManager.java index 280d2de..e6ec6cd 100644 --- a/src/main/java/world/bentobox/greenhouses/managers/GreenhouseManager.java +++ b/src/main/java/world/bentobox/greenhouses/managers/GreenhouseManager.java @@ -139,6 +139,14 @@ public class GreenhouseManager implements Listener { public void removeGreenhouse(Greenhouse g) { handler.deleteObject(g); map.removeGreenhouse(g); + if (g.getOriginalBiome() == null) { + addon.logError("Greenhouse had no original biome: " + g.getLocation()); + return; + } + if (g.getLocation() == null || g.getLocation().getWorld() == null) { + // Greenhouse is messed up. It's being deleted anyway. + return; + } addon.log("Returning biome to original state: " + g.getOriginalBiome().toString()); for (int x = (int)g.getBoundingBox().getMinX(); x<= (int)g.getBoundingBox().getMaxX(); x+=4) { for (int z = (int)g.getBoundingBox().getMinZ(); z<= (int)g.getBoundingBox().getMaxZ(); z+=4) { diff --git a/src/main/java/world/bentobox/greenhouses/managers/GreenhouseMap.java b/src/main/java/world/bentobox/greenhouses/managers/GreenhouseMap.java index a9ac127..4801c1a 100644 --- a/src/main/java/world/bentobox/greenhouses/managers/GreenhouseMap.java +++ b/src/main/java/world/bentobox/greenhouses/managers/GreenhouseMap.java @@ -34,7 +34,7 @@ public class GreenhouseMap { */ public GreenhouseResult addGreenhouse(Greenhouse greenhouse) { // Validation checks - if (greenhouse.getBiomeRecipe() == null) { + if (greenhouse.getBiomeRecipe().getBiome() == null) { return GreenhouseResult.FAIL_UNKNOWN_RECIPE; } if (greenhouse.getWorld() == null) { @@ -105,7 +105,7 @@ public class GreenhouseMap { } private boolean isOverlapping(Greenhouse greenhouse) { - return addon.getIslands().getIslandAt(greenhouse.getLocation()).map(i -> { + return greenhouse.getLocation() != null && addon.getIslands().getIslandAt(greenhouse.getLocation()).map(i -> { greenhouses.putIfAbsent(i, new ArrayList<>()); return greenhouses.get(i).stream().anyMatch(g -> g.getBoundingBox().overlaps(greenhouse.getBoundingBox())); }).orElse(false); @@ -117,9 +117,11 @@ public class GreenhouseMap { * @param greenhouse - greenhouse */ protected void removeGreenhouse(Greenhouse greenhouse) { - addon.getIslands().getIslandAt(greenhouse.getLocation()).ifPresent(i -> { - if (greenhouses.containsKey(i)) greenhouses.get(i).remove(greenhouse); - }); + if (greenhouse.getLocation() != null) { + addon.getIslands().getIslandAt(greenhouse.getLocation()).ifPresent(i -> { + if (greenhouses.containsKey(i)) greenhouses.get(i).remove(greenhouse); + }); + } } /** diff --git a/src/main/java/world/bentobox/greenhouses/ui/panel/PanelClick.java b/src/main/java/world/bentobox/greenhouses/ui/panel/PanelClick.java index 2935861..31479d9 100644 --- a/src/main/java/world/bentobox/greenhouses/ui/panel/PanelClick.java +++ b/src/main/java/world/bentobox/greenhouses/ui/panel/PanelClick.java @@ -43,6 +43,10 @@ public class PanelClick implements ClickHandler { } private boolean makeGreenhouse(User user, BiomeRecipe br) { + if (user.getLocation() == null) { + addon.logError("User has no location : " + user.getName()); + return false; + } // Check flag if (!addon.getIslands().getIslandAt(user.getLocation()).map(i -> i.isAllowed(user, Greenhouses.GREENHOUSES)).orElse(false)) { user.sendMessage("greenhouses.errors.no-rank"); diff --git a/src/main/java/world/bentobox/greenhouses/ui/user/MakeCommand.java b/src/main/java/world/bentobox/greenhouses/ui/user/MakeCommand.java index 6b7a893..0111e2e 100644 --- a/src/main/java/world/bentobox/greenhouses/ui/user/MakeCommand.java +++ b/src/main/java/world/bentobox/greenhouses/ui/user/MakeCommand.java @@ -92,6 +92,10 @@ class MakeCommand extends CompositeCommand { * @return true if successful */ private boolean makeGreenhouse(User user, BiomeRecipe br) { + if (user.getLocation() == null) { + getAddon().logError("User had no location"); + return false; + } // Check flag if (!getIslands().getIslandAt(user.getLocation()).map(i -> i.isAllowed(user, Greenhouses.GREENHOUSES)).orElse(false)) { user.sendMessage("greenhouses.errors.no-rank"); diff --git a/src/main/java/world/bentobox/greenhouses/ui/user/RemoveCommand.java b/src/main/java/world/bentobox/greenhouses/ui/user/RemoveCommand.java index 49ca538..8ae6a8f 100644 --- a/src/main/java/world/bentobox/greenhouses/ui/user/RemoveCommand.java +++ b/src/main/java/world/bentobox/greenhouses/ui/user/RemoveCommand.java @@ -35,6 +35,10 @@ class RemoveCommand extends CompositeCommand { */ @Override public boolean execute(User user, String label, List args) { + if (user.getLocation() == null) { + getAddon().logError("User had no location"); + return false; + } // Check flag if (!getIslands().getIslandAt(user.getLocation()).map(i -> i.isAllowed(user, Greenhouses.GREENHOUSES)).orElse(false)) { user.sendMessage("greenhouses.errors.no-rank"); diff --git a/src/main/java/world/bentobox/greenhouses/world/AsyncWorldCache.java b/src/main/java/world/bentobox/greenhouses/world/AsyncWorldCache.java index f13f059..05c5ce0 100644 --- a/src/main/java/world/bentobox/greenhouses/world/AsyncWorldCache.java +++ b/src/main/java/world/bentobox/greenhouses/world/AsyncWorldCache.java @@ -2,6 +2,7 @@ package world.bentobox.greenhouses.world; import java.util.HashMap; import java.util.Map; +import java.util.Objects; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; @@ -101,7 +102,7 @@ public class AsyncWorldCache { int xx = x >= 0 ? x % 16 : (16 + (x % 16)) % 16; int zz = z >= 0 ? z % 16 : (16 + (z % 16)) % 16; try { - return getSnap(x,z).getBlockType(xx, y, zz); + return Objects.requireNonNull(getSnap(x, z)).getBlockType(xx, y, zz); } catch (InterruptedException | ExecutionException e) { Greenhouses.getInstance().logError("Chunk could not be obtained async! " + e); // Restore interrupted state... diff --git a/src/test/java/world/bentobox/greenhouses/data/GreenhouseTest.java b/src/test/java/world/bentobox/greenhouses/data/GreenhouseTest.java index b4063bd..6665f0d 100644 --- a/src/test/java/world/bentobox/greenhouses/data/GreenhouseTest.java +++ b/src/test/java/world/bentobox/greenhouses/data/GreenhouseTest.java @@ -293,7 +293,7 @@ public class GreenhouseTest { */ @Test public void testGetMissingBlocks() { - assertNull(gh.getMissingBlocks()); + assertNotNull(gh.getMissingBlocks()); } }