Prevents mobs from spawning in the greenhouse wall

https://github.com/BentoBoxWorld/Greenhouses/issues/26

Some large mobs can spawn next to the wall and pop out of the
greenhouse. This deletes them if they are too big.
This commit is contained in:
tastybento 2019-10-17 22:37:27 -07:00
parent 15b2c63450
commit 29fd573d0c
4 changed files with 94 additions and 3 deletions

View File

@ -51,7 +51,7 @@
<!-- Revision variable removes warning about dynamic version -->
<revision>${build.version}-SNAPSHOT</revision>
<!-- This allows to change between versions and snapshots. -->
<build.version>0.4.1</build.version>
<build.version>0.4.2</build.version>
<build.number>-LOCAL</build.number>
</properties>

View File

@ -12,6 +12,7 @@ import java.util.Set;
import java.util.TreeMap;
import java.util.stream.Collectors;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.Particle;
import org.bukkit.block.Biome;
@ -19,7 +20,10 @@ import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.block.data.Bisected;
import org.bukkit.block.data.BlockData;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.util.BoundingBox;
import org.bukkit.util.Vector;
import world.bentobox.bentobox.util.Util;
import world.bentobox.greenhouses.Greenhouses;
@ -294,11 +298,31 @@ public class BiomeRecipe implements Comparable<BiomeRecipe> {
if (b.getY() == 0) {
return false;
}
// Center spawned mob
Location spawnLoc = b.getLocation().clone().add(new Vector(0.5, 0, 0.5));
return getRandomMob()
// Check if the spawn on block matches, if it exists
.filter(m -> m.getMobSpawnOn().map(b.getRelative(BlockFace.DOWN).getType()::equals).orElse(true))
// If spawn occurs, return true
.map(m -> b.getWorld().spawnEntity(b.getLocation(), m.getMobType()) != null).orElse(false);
// If spawn occurs, check if it can fit inside greenhouse
.map(m -> {
Entity entity = b.getWorld().spawnEntity(spawnLoc, m.getMobType());
if (entity != null) {
return addon
.getManager()
.getMap()
.getGreenhouse(b.getLocation()).map(gh -> {
BoundingBox interior = gh.getBoundingBox().clone();
interior.expand(-1, -1, -1);
if (!interior.contains(entity.getBoundingBox())) {
entity.remove();
return false;
}
return true;
}).orElse(false);
}
return false;
}).orElse(false);
}
/**

View File

@ -78,6 +78,16 @@ public class GreenhouseMap {
return getGreenhouse(location).isPresent();
}
/**
* Check if a location is in a specific greenhouse
* @param gh - greenhouse
* @param location - location to check
* @return true if inside
*/
public boolean inGreenhouse(Greenhouse gh, Location location) {
return getGreenhouse(location).map(gh::equals).orElse(false);
}
/**
* Check if location is above a greenhouse
* @param location - location
@ -135,4 +145,6 @@ public class GreenhouseMap {
public int getSize() {
return greenhouses.values().stream().mapToInt(List::size).sum();
}
}

View File

@ -12,6 +12,7 @@ import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.util.Optional;
import java.util.Set;
import org.bukkit.Bukkit;
@ -28,7 +29,9 @@ import org.bukkit.block.data.BlockData;
import org.bukkit.entity.Cat;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.scheduler.BukkitScheduler;
import org.bukkit.util.BoundingBox;
import org.bukkit.util.Vector;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@ -40,7 +43,9 @@ import org.powermock.modules.junit4.PowerMockRunner;
import world.bentobox.bentobox.BentoBox;
import world.bentobox.greenhouses.Greenhouses;
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;
/**
* @author tastybento
@ -67,6 +72,14 @@ public class BiomeRecipeTest {
private Location location;
@Mock
private BlockData bd;
@Mock
private BentoBox plugin;
@Mock
private GreenhouseManager mgr;
@Mock
private GreenhouseMap map;
@Mock
private BukkitScheduler scheduler;
/**
* @throws java.lang.Exception
@ -93,6 +106,8 @@ public class BiomeRecipeTest {
Material.AIR);
when(block.getWorld()).thenReturn(world);
when(block.getLocation()).thenReturn(location);
when(location.clone()).thenReturn(location);
when(location.add(any(Vector.class))).thenReturn(location);
// Set up default recipe
br = new BiomeRecipe(addon, type, 0);
br.setIcecoverage(2); // 1%
@ -103,6 +118,17 @@ public class BiomeRecipeTest {
br.setName("name2");
br.setIcon(Material.ACACIA_BOAT);
br.setPermission("perm");
// Plugin
when(addon.getPlugin()).thenReturn(plugin);
// Manager
when(addon.getManager()).thenReturn(mgr);
// GH Map
when(mgr.getMap()).thenReturn(map);
Optional<Greenhouse> optionalGh = Optional.of(gh);
when(map.getGreenhouse(any(Location.class))).thenReturn(optionalGh);
// Bukkit Scheduler
when(Bukkit.getScheduler()).thenReturn(scheduler);
}
/**
@ -360,6 +386,31 @@ public class BiomeRecipeTest {
assertFalse(br.spawnMob(block));
}
/**
* Test method for {@link world.bentobox.greenhouses.greenhouse.BiomeRecipe#spawnMob(org.bukkit.block.Block)}.
*/
@Test
public void testSpawnMobOutsideWall() {
when(block.getY()).thenReturn(10);
when(block.getType()).thenReturn(Material.GRASS_PATH);
when(block.getRelative(any())).thenReturn(block);
EntityType mobType = EntityType.CAT;
int mobProbability = 100;
Material mobSpawnOn = Material.GRASS_PATH;
Entity cat = mock(Cat.class);
// Same box as greenhouse
when(cat.getBoundingBox()).thenReturn(bb);
when(world.spawnEntity(any(), any())).thenReturn(cat);
br.addMobs(mobType, mobProbability, mobSpawnOn);
assertFalse(br.spawnMob(block));
verify(world).spawnEntity(eq(location), eq(EntityType.CAT));
verify(location).add(any(Vector.class));
}
/**
* Test method for {@link world.bentobox.greenhouses.greenhouse.BiomeRecipe#spawnMob(org.bukkit.block.Block)}.
*/
@ -374,12 +425,16 @@ public class BiomeRecipeTest {
Material mobSpawnOn = Material.GRASS_PATH;
Entity cat = mock(Cat.class);
// Exactly 1 block smaller than the greenhouse blocks
BoundingBox small = new BoundingBox(11, 101, 11, 19, 119, 19);
when(cat.getBoundingBox()).thenReturn(small);
when(world.spawnEntity(any(), any())).thenReturn(cat);
br.addMobs(mobType, mobProbability, mobSpawnOn);
assertTrue(br.spawnMob(block));
verify(world).spawnEntity(eq(location), eq(EntityType.CAT));
verify(location).add(any(Vector.class));
}
/**